@16x/webphone-sdk 3.1.17 → 3.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +267 -31
  2. package/LICENSE +1 -1
  3. package/README.md +214 -161
  4. package/dist/{Diagnostics-CK0ai_sy.cjs → Diagnostics-CgDSPlQx.cjs} +1 -1
  5. package/dist/{Diagnostics-B6xGNl8M.js → Diagnostics-DJdBDGad.js} +1 -1
  6. package/dist/{JsSipAdapter-l97xq1ao.cjs → JsSipAdapter-CgBtmR16.cjs} +1 -1
  7. package/dist/{JsSipAdapter-B8ueIoBA.js → JsSipAdapter-CiqM4KOq.js} +1 -1
  8. package/dist/SharedWorkerProtocol-4VARy5ma.cjs +1 -0
  9. package/dist/SharedWorkerProtocol-DvLUl0JZ.js +93 -0
  10. package/dist/core/CCBarCall.d.ts +1 -1
  11. package/dist/createJsSipFactory-9CPsweDR.js +9665 -0
  12. package/dist/createJsSipFactory-Dr8HbLl-.cjs +75 -0
  13. package/dist/crypto/legacySipTicket.d.ts +40 -0
  14. package/dist/diagnostics/index.cjs +1 -1
  15. package/dist/diagnostics/index.js +1 -1
  16. package/dist/errors/CCBarError.d.ts +2 -0
  17. package/dist/i18n/index.d.ts +22 -0
  18. package/dist/i18n/messages/en-US.d.ts +2 -0
  19. package/dist/i18n/messages/es-ES.d.ts +2 -0
  20. package/dist/i18n/messages/id-ID.d.ts +2 -0
  21. package/dist/i18n/messages/index.d.ts +7 -0
  22. package/dist/i18n/messages/zh-CN.d.ts +2 -0
  23. package/dist/i18n/types.d.ts +5 -0
  24. package/dist/i18n-BbEy6K9z.cjs +1 -0
  25. package/dist/i18n-D-DdHtGz.js +150 -0
  26. package/dist/index.cjs +1 -1
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.js +9 -8
  29. package/dist/index.umd.js +69 -16
  30. package/dist/legacy/index.cjs +1 -1
  31. package/dist/legacy/index.js +10 -276
  32. package/dist/legacy/legacySessionProvider.d.ts +20 -9
  33. package/dist/legacySessionProvider-CKJyrade.cjs +1 -0
  34. package/dist/{CCBarClient-C2sC86Xi.js → legacySessionProvider-DBrRBB3S.js} +795 -493
  35. package/dist/shared/SharedWorkerFactory.d.ts +2 -0
  36. package/dist/shared/SharedWorkerProtocol.d.ts +2 -0
  37. package/dist/shared-worker.cjs +1 -1
  38. package/dist/shared-worker.js +65 -64
  39. package/dist/styles.css +7 -7
  40. package/dist/ui/i18n/es-ES.d.ts +2 -0
  41. package/dist/ui/i18n/id-ID.d.ts +2 -0
  42. package/dist/ui/i18n/index.d.ts +2 -0
  43. package/dist/ui/index.cjs +1 -1
  44. package/dist/ui/index.js +278 -170
  45. package/dist/version.d.ts +1 -1
  46. package/package.json +114 -109
  47. package/dist/CCBarClient-GQ3yxDur.cjs +0 -1
  48. package/dist/SharedWorkerProtocol-C-4KpECM.cjs +0 -1
  49. package/dist/SharedWorkerProtocol-CffZrUXg.js +0 -119
  50. package/dist/createJsSipFactory-B1ORbJiP.cjs +0 -22
  51. package/dist/createJsSipFactory-CoWZN-BC.js +0 -7410
package/CHANGELOG.md CHANGED
@@ -1,31 +1,267 @@
1
- # Changelog
2
-
3
- ## 3.1.17
4
-
5
- 修复平台抖动后 dial 永久不可自愈(CALL_NOT_CONNECTED)——与主线 3.2.8 同源修复:
6
-
7
- - `ReconnectManager` 新增 `isRecovered` 校验:recover() 成功返回不再被当作连接已恢复,未恢复按失败继续退避。
8
- - `recoverInvalidSession` 重建失败不再 `reconnect.cancel()` 永久取消重连循环(事故主根因),保持封顶退避重试。
9
- - `recoverConnection` 在会话被清空后改走 `performConnect` 全新建会话;在途通话超过 120s 宽限后强制终态(终态事件不可达时)。
10
- - 媒体释放屏障增加 5s 超时,防止永不 settle 的释放操作锁死重连。
11
-
12
- ## 3.1.16 - 2026-10-08
13
-
14
- - 修正客户专属发布版本号与 npm dist-tag 对齐;此版本运行时代码与 3.1.15 相同。
15
-
16
- ## 3.1.15 - 2026-10-08
17
-
18
- - 回移 3.2.6–3.2.7 的 ICE 改进:增加 ICE gathering 3 秒兜底、按 URL 探测 ICE 服务,并将探测结果区分为可用、不可用和未知。
19
- - 探测在后台运行,不阻塞拨号;未知结果不永久删除 ICE 地址。后续新通话可使用 5 分钟内最近验证可用的配置,并在网络恢复、SIP 重连、ICE 失败或缓存过期时重新探测。
20
- - 增加有退避上限的重试及 ICE 诊断字段。
21
- - 保持 3.1.x 客户服务端 `getToken`、`getAccount` 和会话组装流程不变;未更改 SDK 的双接口对接契约。
22
-
23
- ## 3.1.12 - 2026-10-06
24
-
25
- - 保持既有 `sessionProvider` 接入契约:客户服务端继续完成 `getToken`、`getAccount` 和会话组装,SDK 接收完整会话;本版本不改变该流程。
26
- - 升级 JsSIP 到 3.13.8。
27
- - 增加外呼号码与 SIP URI 格式校验,非法目标在创建 SIP 通话前返回 `CALL_INVALID_DESTINATION`。
28
- - hold/unhold 操作失败时保留底层原因;区分本地保持与远端保持,并拒绝不适用的本地恢复操作。
29
- - `CCBarError` 增加客户可读的 `message`,保留稳定字符串 `code`,并支持传递平台数字 `platformCode`。
30
- - 合并并发 `client.connect()` 调用,避免重复执行凭证失效钩子;坐席状态在运行时校验。
31
- - 改进内置通话组件的错误提示展示。
1
+ # Changelog
2
+
3
+ ## 3.1.19
4
+
5
+ 新增 i18n 多语言支持(中文 / 英文 / 印尼语 / 西班牙语):
6
+
7
+ - 新增 `src/i18n` 四语言错误消息表;`CCBarClient` 构造时按 `options.locale` 设置语言,未传时回落浏览器语言(`navigator.language`),最后默认 `zh-CN`;BCP 47 前缀归一化(`zh` → `zh-CN`、`in-ID` → `id-ID` 等),未知语言回落默认。
8
+ - `CCBarError` 构造时按当前语言输出文案,新增 `localizedMessage(locale?)` 按指定语言取文案。
9
+ - SharedWorker attach 请求携带 locale,worker 侧错误文案与页面侧保持一致。
10
+ - UI 组件(XCallCCBarElement)文案由 `locale` 属性决定,新增印尼语 / 西班牙语两套 UI 文案。
11
+
12
+ ## 3.2.9
13
+
14
+ 修复通话失败原因被统一包装成「当前通话状态不支持此操作」的误导文案:
15
+
16
+ - `CallManager.failureError` 新增 SIP 拒绝载荷映射:对方挂断/平台拒绝(480/488/4xx-6xx 家族)→ `CALL_REJECTED`("对方或呼叫平台拒绝了本次呼叫"),486/BUSY → `CALL_BUSY`,408/Request Timeout → `NETWORK_TIMEOUT`。
17
+ - 此前 JsSIP 原始失败载荷(`{originator:'remote', message:{data:'SIP/2.0 4xx…'}}`)一律落入 `CALL_OPERATION_NOT_ALLOWED` 兜底,文案指向状态机,严重误导排障方向(实测复现:拨不存在分机收到 480、平台 488 拒绝时均显示"当前通话状态不支持此操作")。原始载荷完整保留在 `error.cause`。
18
+ - 无 SIP 信息的未知载荷行为不变(仍为 `CALL_OPERATION_NOT_ALLOWED`),`CALL_REJECTED`/`CALL_BUSY` 错误码自此真正被 SIP 层触发。
19
+
20
+ ## 3.2.8
21
+
22
+ 修复平台抖动后 dial 永久不可自愈(CALL_NOT_CONNECTED):
23
+
24
+ - `ReconnectManager` 新增 `isRecovered` 校验:recover() 成功返回不再被当作连接已恢复,未恢复按失败继续退避。
25
+ - `recoverInvalidSession` 重建失败不再 `reconnect.cancel()` 永久取消重连循环(3.2.7 事故主根因),保持封顶退避重试。
26
+ - `recoverConnection` 在会话被清空后改走 `performConnect` 全新建会话;在途通话超过 120s 宽限后强制终态(终态事件不可达时)。
27
+ - 媒体释放屏障增加 5s 超时,防止永不 settle 的释放操作锁死重连。
28
+
29
+ ## 3.2.7 - 2026-10-08
30
+
31
+ - Treat ICE probe timeouts as unknown instead of permanently marking servers unavailable; preserve
32
+ the original ICE pool for later re-probing.
33
+ - Keep ICE probing in the background so it does not block dialing. Use recently available ICE
34
+ servers for new calls with a five-minute cache, and re-probe after network recovery, SIP
35
+ reconnection, ICE failure, or cache expiry.
36
+ - Add bounded retry backoff and diagnostics for probe state, unknown/unavailable URL counts, cache
37
+ age, and the ICE configuration selected for the next call.
38
+
39
+ ## 3.2.6 - 2026-10-07
40
+
41
+ - Fix the multi-egress-office dial delay at its root: a dead STUN/TURN-UDP endpoint dragged JsSIP's
42
+ non-trickle ICE gathering through the browser retransmission tables (~40s measured with both
43
+ STUN binding and TURN allocation retrying in parallel) even though a usable TURN-TCP relay
44
+ candidate was already available at ~150ms.
45
+ - Attach an ICE gathering timeout to every outgoing/incoming session: call JsSIP's built-in
46
+ `icecandidate` `ready()` shortcut as soon as an srflx/relay candidate arrives, and force-close
47
+ the local SDP with the most recent ready callback after 3s so INVITE/200 OK never waits for
48
+ dead servers (mirrors ccbar BUG-013).
49
+ - Add URL-level ICE server probing after each successful registration (`iceServerQuality`):
50
+ every stun/turn/turns URL is probed with its own PeerConnection (credentials inherited);
51
+ URLs that yield no srflx/relay are dropped from the dial-time pcConfig. Healthy networks keep
52
+ the original list unchanged (zero behavior change); when every URL fails the list becomes
53
+ host-only so the INVITE still goes out immediately. Attribution must be per-URL because relay
54
+ candidates always report `protocol: udp` (it describes the relayed port, not the client
55
+ transport) and mixing dead and live URLs in one probe drags them all to timeout.
56
+ - `getDiagnostics()` now includes an `ice.probe` summary (runs / lastMs / udpOk / tcpRelayOk /
57
+ convergedServers) from the tab-local adapter (absent in SharedWorker mode).
58
+ - Correct the `warmIceCandidatePool` comment: `iceCandidatePoolSize` is per-RTCPeerConnection,
59
+ so warmed candidates cannot transfer to call connections — the timeout + convergence above
60
+ are the actual safeguards. `answer()` now also passes `iceCandidatePoolSize`.
61
+
62
+ ## 3.2.5 - 2026-10-06
63
+
64
+ - Keep held-call state synchronized with the call controls so resume, hangup, and DTMF remain available after a hold transition.
65
+ - Show a specific authentication-token-unavailable message in the embedded phone UI and document the recovery steps.
66
+
67
+ ## 3.2.4 - 2026-10-05
68
+
69
+ - Prevent overlapping hold/resume requests and include actionable `cause.reason` values when an operation is already pending or JsSIP rejects a hold change.
70
+ - Track local and remote hold origins separately; reject a local resume request while only the remote party has held the call.
71
+ - Document hold/resume completion and diagnostic causes.
72
+
73
+ ## 3.2.3 - 2026-10-04
74
+
75
+ - Give `CCBarError.message` customer-readable Chinese text while keeping stable string `code` values for programmatic handling.
76
+ - Preserve numeric platform response codes as optional `platformCode`; normalize token rejection from the seat account API without mislabeling every 401 as an expired token.
77
+ - Carry `platformCode` and readable messages through SharedWorker serialization.
78
+
79
+ ## 3.2.2 - 2026-10-04
80
+
81
+ - Reject malformed outbound destinations before creating a call or sending a SIP INVITE; preserve 3–20 digit phone numbers and SIP/SIPS URI destinations.
82
+ - Document the destination formats and the non-retryable `CALL_INVALID_DESTINATION` error.
83
+
84
+ ## 3.2.1 - 2026-10-04
85
+
86
+ - 修复运行时传入不支持的坐席状态(例如 `busy`)时出现未处理 TypeError 的问题;现在会返回明确的 `CONFIG_INVALID` SDK 错误,并且不会发送状态请求。
87
+ - 明确覆盖 `getToken()` 返回 `accessToken`、但账号接口拒绝该凭证时的认证错误信息,便于接入方定位凭证类型或权限问题。
88
+
89
+ ## 3.2.0 - 2026-10-03
90
+
91
+ - 新增 `createTokenSessionProvider` 根入口,客户可通过 `getToken` 提供短期凭证;SDK 内部完成坐席账号获取、SIP 会话创建、注册登录、凭证刷新和坐席状态请求。
92
+ - 重复调用 `client.connect()` 时复用进行中的连接流程,已连接时直接返回,避免重复获取凭证和重复初始化连接。
93
+ - 完善接入文档,说明连接、坐席、通话状态,事件与错误处理,以及 `userdata` 到 SIP header 和话单字段的映射方式。
94
+ - 补充 9196、9199 实时验收及凭证错误、网络中断、STUN 异常和资源清理场景。
95
+
96
+ ## 3.1.11 - 2026-09-30
97
+
98
+ - **破坏性变更(会话来源)**:会话来源工厂的 `sipWsUrl` 改为**必填**,软电话地址
99
+ 由接入方传完整地址(`wss://` / `ws://`)。SDK 不再按坐席账号的 `domain` / `wssPort`(缺省 7443)
100
+ 与固定路径 `/api/fs/sip-ws` 拼装,`sipWsPath` 选项删除;缺 `sipWsUrl`、传相对路径或 `http(s)://`
101
+ 地址时,建会话(`createSession` / `refreshSession`)抛 `CONFIG_INVALID`(**构造本身不抛**)。
102
+ - 地址上已有的查询参数保留,SDK 仍把 fs token 挂成 `?token=`(`attachTokenToWss: false` 可关掉)。
103
+ - 只影响使用兼容会话入口的调用方;服务端下发完整 `transport.wssUrl` 的接入方式不受影响。
104
+
105
+ ## 3.1.10 - 2026-09-24
106
+
107
+ - **会话入口自动识别密文**:接入方把 `seat/account/get` 返回的 `password` 密文**直接**塞进
108
+ `session.sip.registerTicket` 时,SDK 现在会在会话进入的那一处(`createSessionProviderApi`)
109
+ 先用平台内置 key/iv 解一次,解不出来就原样放行 —— 服务端因此可以只做转发,
110
+ 不必再自己调 `decryptSipPassword`。
111
+ - 判定条件收得很紧,避免把明文密码当密文解坏:合法 Base64、长度是 4 的倍数、解码后是 16 字节的整数倍、
112
+ AES 解出的文本没有替换符与控制字符。固定种子采样(字母数字 8~40 位、32 位十六进制、
113
+ 以及「刚好是 16 字节 Base64 带 `=` 填充」这种最危险的形状)实测没有误判。
114
+ - 只认平台内置的 key/iv(即 `decryptSipPassword` 的默认值):环境不同、key/iv 被改过时,
115
+ 自动判定会失败并退回原值,这种环境仍需接入方自己用 `decryptSipPassword(cipher, { key, iv })`
116
+ 解好再放进会话。
117
+ - 非破坏性:已经自行解密的接入方拿到的会话对象原样不变;`decryptSipPassword` 的实现移入独立加密模块,
118
+ 公开导出与行为保持不变。
119
+
120
+ ## 3.1.9 - 2026-09-24
121
+
122
+ - **坐席状态接口直接用会话里的那张票**:平台把 fs token 拼在软电话地址上(`wss://…/api/fs/sip-ws?token=…`),
123
+ 同一个 token 也用于 HTTP 接口的 `Authorization`。`client.setAgentStatus()` 现在把这个地址带给会话来源
124
+ (`SessionProvider.setAgentStatus(request, context?)`,新增可选参数 `AgentStatusContext.wssUrl`),
125
+ 订阅来源可以直接拿它去打 `seat/account/get` 与 `seats/set-status`,**不再单独换一次票**。
126
+ - 会话来源的 `setAgentStatus` 按这个顺序取票:
127
+ 会话地址里的 token → 最近见过的那个(退签时会话已经断开)→ `getToken`/`tokenUrl` 重新换票(与旧行为一致)。
128
+ 它自己在 `createSession` 里拼过 WSS 地址时也会记住那张票;`invalidateToken()` 会把它一起清掉。
129
+ - 非破坏性:`setAgentStatus` 的第二个参数是可选的,旧接入方(不传 context、只用 `getToken`/`tokenUrl`)行为不变。
130
+
131
+ ## 3.1.8 - 2026-09-23
132
+
133
+ - **修 3.1.7 引入的回归:来电会被立刻拒掉(对端收到 480)。**
134
+ 3.1.7 新加的 `mediaConnected` 订阅在「会话还没有 PeerConnection」时崩了:JsSIP 的
135
+ `session.connection` 在 PC 建好之前返回的是 **`null`,不是 `undefined`**(来电要等 `answer()`
136
+ 才建 PC),而那处只判了 `undefined` → `null.addEventListener` 抛 TypeError →
137
+ `CCBarCall` 构造函数的 catch 里 `terminate()` → 页面收到一个包着 `CALL_OPERATION_NOT_ALLOWED`
138
+ 的错误,对端收到 `480 Temporarily Unavailable`(SIP 原文里是 `newRTCSession` 后 1ms 就 `terminate`)。
139
+ 现在按 `null` 处理:PC 还没建就只挂 `peerconnection` 监听,等它出现再挂 `connectionstatechange`。
140
+ - 同一处一并修了 `getMediaRegistration()`:PC 还没建时不再拿 `null` 去建媒体注册对象
141
+ (那个对象之后一被用就会抛;来电在 answer 之后的状态变化里会重新注册,不受影响)。
142
+ - 类型跟着改了:`jsSipTypes.ts` 里 `connection` 声明为 `RTCPeerConnection | null` ——
143
+ 这个 bug 正是被「只写了 undefined」的类型漏过去的,改完之后 `tsc` 会把同类问题拦住。
144
+ - 补用例:会话 `connection` 为 `null` 时订阅 `mediaConnected` 不能抛;测试里的假 JsSIP 会话
145
+ 现在默认就是 `null`(与真实 JsSIP 一致)。
146
+
147
+
148
+ ## 3.1.7 - 2026-09-23
149
+
150
+ - **`active` 不再只认 SIP 的 ACK**:新增会话事件 `mediaConnected` —— 媒体真的通了(ICE + DTLS 完成)时,
151
+ 只要通话已经进入 `connecting` 就推进到 `active`。
152
+ 背景:`active` 原来只由 JsSIP 的 `confirmed` 驱动,而它要等对端回 ACK。有些平台(SBC)不回 ACK:
153
+ 200 OK 之后音频已经通了、双方都在通话,`confirmed` 却永远不来,页面就一直停在「接通中」
154
+ (3.1.6 之前停在「振铃中」,那是同一现象的另一个表现,见 3.1.6 第一条)。
155
+ - 只从 `connecting` 推进:`ringing` / `dialing` 阶段的连接可能只是早期媒体(回铃),不算接通。
156
+ - `CallSessionEvent` 增加 `'mediaConnected'`(新增事件,对已有集成无影响);JsSIP 适配器在
157
+ PeerConnection 的 `connectionstatechange` 变成 `connected` 时发一次,通话结束时撤掉会话上的订阅。
158
+ - 仍未解决、且**在平台侧**的一点:如果平台始终不回 ACK,JsSIP 自己的 ACK 定时器会在 32 秒后以
159
+ `NO_ACK` 结束这通电话。SDK 不能替对端回 ACK,只能让状态先跟上事实;平台侧需补齐 ACK。
160
+
161
+
162
+ ## 3.1.6 - 2026-09-23
163
+
164
+ - **接听后立刻进入 `connecting`**:原来要等 JsSIP 的 `accepted`(也就是 200 OK 真发出去之后)才动状态。
165
+ 背景:`answer()` 只让 JsSIP 同步进入 ANSWERED,200 OK 还要等本地媒体/SDP 准备好(首次通话还要等
166
+ 麦克风授权),这十几秒里状态一直停在 `ringing` —— 页面上就是「点了接听没反应、状态还是振铃中」,
167
+ 用户会以为没接上。现在点完接听立刻走 `ringing → connecting`,随后的 `accepted` / `confirmed`
168
+ 照旧推到 `active`(公开状态链 `ringing→connecting→active` 不变,已有用例覆盖)。
169
+ - 修 `hangup()`:terminate 之后若通话已被推成终态(JsSIP 对未确认的来电会**同步**发 `failed`),
170
+ 不再多做一次非法的 `failed → ended` 转换 —— 那一帧会多抛一个 `CALL_OPERATION_NOT_ALLOWED`,
171
+ 页面红字行/日志里就多一条看不懂的报错。
172
+ - 修媒体收尾的噪音:通话结束解绑发送通道时,若连接已经关闭(WebRTC 规定此时 `replaceTrack` 抛
173
+ `InvalidStateError`),按「没有东西可解绑」处理,不再报 `SDK_INTERNAL_ERROR`
174
+ (典型现象:挂断瞬间刷一条 `replaceTrack ... The peer connection is closed`)。
175
+ - 接听 / 拒接失败时**先把原始原因报出来**再 terminate 清理:terminate 会同步触发 JsSIP 的 `failed`
176
+ (cause 固定是 `REJECTED`),原来的原因会被这个终态盖掉 —— 之前只能看到 `REJECTED`,
177
+ 看不到「为什么接听会失败」。现在先经 `error` 事件把原始 cause 带出去。
178
+
179
+
180
+ ## 3.1.5 - 2026-09-23
181
+
182
+ - 新增 `dial({ destination, userdata })`:自定义参数原样写进 INVITE 的 `X-User-Data` 头,由平台/服务端从 SIP
183
+ 报文里读 —— 就是旧版脚本 SDK 的 `userdata`,头名与含义都没变,平台侧不用改。未传、空串、纯空白=不带头
184
+ (与旧行为逐字一致);`dial({ destination, userdata: '' })` 也不会多出任何头。
185
+ - 只接受可见 ASCII:换行/制表能伪造出新的 SIP 头,中文等非 ASCII 不合规(中间设备可能吞掉或改写),
186
+ 两者都抛 `CALL_INVALID_USERDATA`(`category: 'call'`、`retryable: false`,处置建议放在 `cause` 里)。
187
+ 要传中文或 JSON 请调用方先 `encodeURIComponent` / base64,再在平台侧解回来。
188
+ - 校验在建通话之前完成:非法值不占并发额度、也不留 pending —— 否则同号紧接着再拨会撞 `CALL_ALREADY_EXISTS`。
189
+ - 注意:SDK 不暴露 SIP 头,页面侧读不到这个值(`call.incoming` 只给 `callId` / `from`);它是对平台/服务端说的,
190
+ 页面上要排障只能像演示页那样打开 JsSIP 的 debug 抓 console 原文。
191
+
192
+
193
+ ## 3.1.4 - 2026-09-22
194
+
195
+ - **移动端形态(`platform: 'mobile-web'`)可以接来电了**:能不能接听改由会话策略 `policy.mobileIncomingEnabled` 决定
196
+ (这个字段契约里一直有、之前只声明没实现)。打开时保留 `inbound` 能力,来电正常进 `call.incoming`、可以 `answer()`;
197
+ `false` 或缺省时行为与旧版完全一致(来电直接拒掉,`CAPABILITY_NOT_SUPPORTED`)。保持 / 转接仍然不在移动端支持
198
+ (移动 UI 上没有这两个操作),并发数仍是 1。
199
+ - 背景:`mobile-web` 之前无条件删掉 `inbound`,导致手机浏览器「能打出去、别人打不进来」——被叫把 INVITE 直接结束,
200
+ 主叫那边只会看到平台转出来的 `480 Temporarily Unavailable`(`Q.850 cause=16 NORMAL_CLEARING`),页面连来电浮层都不弹。
201
+ 注意 `platform` 不传时 `detectPlatform()` 命中 `iPhone|iPad|Android` 会自动选 `mobile-web`,所以这个坑对手机端接入方是默认生效的。
202
+ - `CallManager.answer` / `CCBarCall.answer` 的「按平台一刀切」改成按能力判断(会话说了算):
203
+ 平台若给移动端授予 `inbound`,同样能正常接听。
204
+
205
+
206
+ ## 3.1.3 - 2026-09-22
207
+
208
+ - 新增可选构造参数 `agentTerminal`:设了就在 INVITE / REGISTER 上带 `X-Agent-Terminal` 并作为 UA 的
209
+ User-Agent。**默认不发**(旧版脚本 SDK 的两种做法都能外呼:xcall fork 带 `'ccbar坐席'`,另一个参考页完全不带)。
210
+ - 会话定时器默认关闭(`session_timers: false`,与旧版脚本 SDK 一致),呼叫参数用 `sessionTimersExpires: 120`:
211
+ 开着时 INVITE 会多出 `Session-Expires` / `Supported: timer`。可用 `sipSessionTimers: true` 打开。
212
+ - 注册成功后先建一个带 `iceCandidatePoolSize` 的空连接预热候选(`warmIceCandidatePool`):
213
+ JsSIP 要等 ICE 收集结束才发 INVITE,机器上有虚拟网卡/不通的 STUN 时收集会拖到几十秒,
214
+ 预热后第一次外呼也能立刻出局。
215
+
216
+
217
+ ## 3.1.2 - 2026-09-21
218
+
219
+ - 拨号更快出局:`pcConfig` 带上 `iceCandidatePoolSize: 2`(与旧版 SDK 的 login config 一致)。
220
+ 背景:JsSIP 会等 ICE 收集完成才发 INVITE,不预收集候选时,STUN 的往返会直接变成「点了外呼要等一会儿才拨出去」。
221
+
222
+
223
+ ## 3.1.1 - 2026-09-21
224
+
225
+ - 新增 SIP 保活:已注册时每 `sipKeepaliveSeconds`(默认 25 秒)重发一次 REGISTER,撑住 nginx/NAT 上的长连接。
226
+ 起因:浏览器发不了 WebSocket ping,中间设备会静默掐掉空闲的 WSS —— 页面还显示已注册,下一次 INVITE 直接
227
+ 失败(`CALL_OPERATION_NOT_ALLOWED`,JsSIP 的 `NotConnected`)。注册有效期本身比间隔短时不再叠这一层。
228
+ 可用构造参数 `sipKeepaliveSeconds` 调整,`0` 关闭。
229
+
230
+
231
+ ## 3.1.0 - 2026-09-21
232
+
233
+ - 新增可选构造参数 `sessionProvider`:由接入方提供会话(`createSession` / 可选 `refreshSession`
234
+ / `setAgentStatus`),SDK 不再要求必须存在 `/webphone/v1/sessions`。用于把 SDK 接到自建服务或既有平台接口
235
+ (例如 `token/fs` + `seat/account/get` 那一套)上,`tokenProvider` 与 `sessionProvider` 二选一。
236
+ - `sessionProvider` 缺省 `refreshSession` 时用 `createSession` 重建;缺省 `setAgentStatus` 时抛
237
+ `CAPABILITY_NOT_SUPPORTED`,不静默失败;没有提供任何来源时构造即报 `CONFIG_INVALID`。
238
+ - `transport.ticket` 为空时不再声明 `xcall-ticket.` 子协议,只发 `sip`:平台把凭据放在
239
+ WSS URL 的 `?token=` 上,多余子协议会让握手带上一个平台不认识的协议名。
240
+ - REGISTER 的 `register_expires` 改为按 `session.sip.registerExpires` 走(原先前端写死 300 秒),
241
+ 会话没给或给了非正数时才回退 300。平台侧要按自己的注册策略下发这个值。
242
+ - 打包脚本在缺少 `zip` 命令的环境(如未装 zip 的 Windows)回退到系统自带 `tar`,交付包仍为 `.zip`。
243
+
244
+ ## 3.0.2 - 2026-09-21
245
+
246
+ - 修复 disconnect 后仍挂着的 `online`/`offline` 监听,以及 `deletedSessions` 墓碑无限增长。
247
+ - `CallManager` 在通话结束通知完成后删除 terminal 记账;`dispose` 仍会清空剩余 maps。
248
+ - `WebPhoneApi` 的 fetch 使用 `credentials: 'omit'`;SIP `wssUrl` 仅允许 `wss:` 或 loopback `ws:`。
249
+ - React / Vue 在应用卸载时 `dispose()`;Vanilla default-ui 与 Mobile H5 通过 `ownsClient` 在组件卸载时释放。
250
+ - 传入 `sharedWorker` 时 `CCBarClient` 会 attach 同源 Worker,并在 `dispose()` 时先 detach 再关闭端口;SIP 仍是单标签页。
251
+ - 诊断报告中的 SDK 版本与 `@16x/webphone-sdk@3.0.2` 对齐。
252
+
253
+ ## 3.0.1 - 2026-09-19
254
+
255
+ - 以 `@16x/webphone-sdk` 发布到 npmjs:https://www.npmjs.com/package/@16x/webphone-sdk
256
+ - 发布 WebPhone SDK 3.0.1,包含 WSS ticket 通过 `Sec-WebSocket-Protocol` 传递及 API 主机相对路径解析修复。
257
+
258
+ ## 0.1.0 - 2026-09-18
259
+
260
+ - 完成 Headless Core 生命周期、SIP/通话控制、媒体设备、重连与脱敏诊断能力。
261
+ - 提供 ESM、CJS、UMD、类型声明及根入口、UI、兼容、诊断与样式入口。
262
+ - 新增 `CCBarSDK` 兼容层,按设计映射连接、拨号、当前通话控制和坐席状态方法。
263
+ - `insideCall(number)` 在当前 `DialOptions` 不支持 `type` 时保留原目标号码,不添加隐式前缀。
264
+ - `setBu()` 改为抛出明确的 `DeprecatedError`,不允许浏览器伪造忙碌状态。
265
+ - 兼容 API 弃用提示仅在开发构建中按方法输出一次;生产构建保持安静。
266
+ - 显式加载兼容入口模块时才在浏览器附加 `window.CCBarSDK`,并保持 SSR 导入安全。
267
+ - 增加 50 次初始化、连接、拨号、结束和销毁生命周期资源回收测试。
package/LICENSE CHANGED
@@ -1 +1 @@
1
- Copyright 16X. All rights reserved.
1
+ Copyright 16X. All rights reserved.