@softomnitel/omnicall-kit 0.1.2 → 0.1.4

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 (2) hide show
  1. package/README.md +64 -2
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -39,6 +39,7 @@ console.log(snapshot.revision);
39
39
  - [Основные понятия](#основные-понятия)
40
40
  - [Состояния и события](#состояния-и-события)
41
41
  - [API Reference](#api-reference)
42
+ - [Форматы успешных ответов](#форматы-успешных-ответов)
42
43
  - [Рецепты](#рецепты)
43
44
  - [Ошибки и FAQ](#ошибки-и-faq)
44
45
  - [Миграция и совместимость](#миграция-и-совместимость)
@@ -66,7 +67,7 @@ npm install @softomnitel/omnicall-kit
66
67
  закрытом npm registry:
67
68
 
68
69
  ```bash
69
- npm install @softomnitel/omnicall-kit@0.1.2
70
+ npm install @softomnitel/omnicall-kit@0.1.4
70
71
  ```
71
72
 
72
73
  Пакет ESM-only. Импортируйте его через `import`, а не `require`.
@@ -101,7 +102,7 @@ const client = createOmniCallClient({
101
102
  url: 'ws://127.0.0.1:17341/omnicall/v1/ws',
102
103
  origin: window.location.origin,
103
104
  application: { name: 'my-crm', version: '1.0.0' },
104
- sdkVersion: '0.1.2',
105
+ sdkVersion: '0.1.4',
105
106
  requestedProfile: 'call_controller',
106
107
  requestedCapabilities: [
107
108
  'session.read.redacted',
@@ -203,9 +204,70 @@ const result = await client.calls.originate({
203
204
  console.log(result.callId, result.revision);
204
205
  ```
205
206
 
207
+ `getRevision()` читает только revision кэшированного snapshot. Успешная мутация
208
+ возвращает новый `result.revision`, но не патчит этот кэш. Для следующей команды
209
+ либо сохраните `result.revision` как локальную последовательность мутаций, либо
210
+ сначала вызовите `getSnapshot()`; после события, reconnect или действий другой
211
+ вкладки выбирайте только свежий snapshot.
212
+
206
213
  Не повторяйте автоматически `originate`, `hangup`, `logout` или
207
214
  `activateProfile` после reconnect. Эти действия могут сработать дважды.
208
215
 
216
+ ## Форматы успешных ответов
217
+
218
+ Асинхронная команда либо завершается типизированным успешным результатом, либо
219
+ отклоняет `Promise` с `OmniCallClientError`. Ошибка никогда не приходит как
220
+ частично успешный объект. Поле `revision` в успешном результате — версия Desktop
221
+ после команды. Это **не** обновляет `getRevision()`: кэш snapshot меняет только
222
+ `getSnapshot()`, а события его не патчат.
223
+
224
+ | Команда | Успешный ответ | Как обрабатывать |
225
+ | --- | --- | --- |
226
+ | `calls.*` | `{ callId, revision }` | Команда принята для этого звонка. Фазу звонка показывайте по событию или snapshot, а не предполагаемому результату команды. |
227
+ | `operator.getReasons()` | `{ reasons: [{ id, label, kind }], revision }` | Фильтруйте по `kind`; в следующую команду передавайте выбранный числовой `id`. |
228
+ | `operator.changeStatus()` | `{ accepted: true, kind, targetStatus, reasonId, revision }` | Обязательно ветвитесь по `kind`: `applied` меняет статус сейчас, `reserved` только бронирует `targetStatus`/`reasonId` до конца обращения. |
229
+ | `operator.finishAppeal()` | Та же форма, что у `changeStatus()` | Разрешён только при `post_call_processing`; применяет бронь либо Desktop-default Ready. |
230
+ | `account.logout()` | `{ loggedOut: true, revision }` | Очищайте UI сессии после ответа/события или подтверждающего snapshot. `interaction_required` — это отклонение Promise, а не вариант успеха. |
231
+ | `account.activateProfile()` | `{ activated: true, mode, profileLabel?, alreadyAuthenticated?, revision }` | `alreadyAuthenticated: true` — успешный no-op. В ответе никогда нет пароля или ключа OCP. |
232
+ | `window.show()` / `hide()` / `getState()` | `{ visible, revision }` | Используйте фактическое `visible`; `show()` и `getState()` не требуют `expectedRevision`. |
233
+
234
+ ### Смена статуса и резервирование
235
+
236
+ `changeStatus()` — единственная публичная команда для намерения Ready/Break.
237
+ Не создавайте отдельный reserve API и не решайте на стороне CRM, занят ли оператор:
238
+ Desktop сам выбирает результат.
239
+
240
+ ```ts
241
+ const result = await client.operator.changeStatus({
242
+ target: 'break',
243
+ reasonId: 12,
244
+ expectedRevision: await getRevision()
245
+ });
246
+
247
+ if (result.kind === 'applied') {
248
+ // targetStatus применён сейчас; обновление UI всё равно подтвердят событие/snapshot.
249
+ } else {
250
+ // Бронь после текущего обращения: текущий статус-chip не становится Break.
251
+ // result.targetStatus и result.reasonId — забронированные значения.
252
+ }
253
+ ```
254
+
255
+ При `kind: 'reserved'` текущий публичный статус может остаться `unknown` во
256
+ время звонка или стать `post_call_processing` после него. Долгоживущую бронь
257
+ восстанавливайте только из свежего
258
+ `snapshot.sections.operator?.reservedTarget` /
259
+ `reservedReasonId` или `operator:status-changed`, особенно после reconnect.
260
+
261
+ Когда snapshot показывает `post_call_processing`, вызовите
262
+ `finishAppeal({ expectedRevision })`. Его успешный ответ имеет ту же форму:
263
+ `kind: 'applied'`, `targetStatus` и `reasonId` — значения, фактически применённые
264
+ Desktop. Вне post-call команда отклоняется `conflict`
265
+ (`failure_kind: 'not_in_post_call_processing'`); ждите корректный snapshot, а не
266
+ повторяйте запрос в цикле.
267
+
268
+ `error.details` остаётся расширяемым объектом. Не разбирайте его произвольные
269
+ поля: используйте type guard и `read*Details` из раздела API Reference.
270
+
209
271
  ## Состояния и события
210
272
 
211
273
  ### Состояния подключения
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softomnitel/omnicall-kit",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Browser client for OmniCall Desktop local protocol (OmniCallClient read path + call control)",
5
5
  "type": "module",
6
6
  "private": false,