@taskless-app/shared 0.1.30 → 0.1.32
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.
- package/dist/transcriptCoverage.d.ts +154 -11
- package/dist/transcriptCoverage.js +144 -7
- package/dist/transcriptCoverage.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,19 +4,29 @@ import { z } from "zod";
|
|
|
4
4
|
* знает, была ли подписка и шли ли PCM-кадры; здесь мы её читаем.
|
|
5
5
|
*
|
|
6
6
|
* `not_subscribed` — публиковал аудио, а рекордера на дорожке не было ни разу;
|
|
7
|
+
* `track_unseen` — дорожка БЫЛА, а агент её не увидел (v6, TAS-536). Доказано
|
|
8
|
+
* одним из двух: комната называла человека активным
|
|
9
|
+
* говорящим (это считает SFU по звуку публикующей стороны и
|
|
10
|
+
* рассылает всем — мимо наших подписок), либо у него висели
|
|
11
|
+
* неподписанные публикации. Дейли 18.08: Дмитрий Гребенев
|
|
12
|
+
* отвечал 102 секунды, его слышали все, Сергей поблагодарил
|
|
13
|
+
* по имени — а в отчёте он «аудио не публиковал»;
|
|
7
14
|
* `no_track` — аудио не публиковал ВОВСЕ, но просидел в комнате дольше
|
|
8
15
|
* порога сверки присутствия (пять минут). Про этих людей до
|
|
9
16
|
* TAS-511 отчёт говорил «слушатель»: Дима Гальянов, 39 минут
|
|
10
|
-
* в звонке, ноль реплик — и ни строки о нём в логе
|
|
17
|
+
* в звонке, ноль реплик — и ни строки о нём в логе агента.
|
|
18
|
+
* С v6 это ровно «микрофон не включали»: признаков дорожки
|
|
19
|
+
* нет ни одного, и раньше сюда же уезжала потеря;
|
|
11
20
|
* `no_audio` — подписка была, но ни одного кадра не доехало;
|
|
12
21
|
* `suppressed` — сегменты распознавались, но их выбрасывал анти-дубль
|
|
13
22
|
* «участник вышел» (собственно баг PRJ3-101).
|
|
14
23
|
*
|
|
15
24
|
* Молчавших и слушателей здесь НЕТ: их ноль объяснён, и сигналом он не
|
|
16
|
-
* является — иначе предупреждение висело бы на каждом созвоне.
|
|
17
|
-
*
|
|
25
|
+
* является — иначе предупреждение висело бы на каждом созвоне. Границу между
|
|
26
|
+
* «слушал» и «не слышали» проводит время в комнате, а границу между «не
|
|
27
|
+
* включал микрофон» и «не увидели дорожку» — доказательство, а не время.
|
|
18
28
|
*/
|
|
19
|
-
export declare const TranscriptCoverageGapReason: z.ZodEnum<["not_subscribed", "no_track", "no_audio", "suppressed"]>;
|
|
29
|
+
export declare const TranscriptCoverageGapReason: z.ZodEnum<["not_subscribed", "track_unseen", "no_track", "no_audio", "suppressed"]>;
|
|
20
30
|
export type TranscriptCoverageGapReason = z.infer<typeof TranscriptCoverageGapReason>;
|
|
21
31
|
/**
|
|
22
32
|
* Отчёт агента за одну сессию.
|
|
@@ -33,7 +43,17 @@ export declare const TranscriptCoverage: z.ZodObject<{
|
|
|
33
43
|
* комнате дольше пяти минут без единой дорожки, теперь gap с причиной
|
|
34
44
|
* `no_track`, а не слушатель; v4 (TAS-509) — появился `audioStall`;
|
|
35
45
|
* v5 (TAS-524) — появились `window` и `jobId`: отчёт наконец говорит, за
|
|
36
|
-
* какой отрезок он
|
|
46
|
+
* какой отрезок он отвечает; v6 (TAS-536) — `no_track` разошёлся надвое:
|
|
47
|
+
* «микрофон не включали» остался `no_track`, а доказанная потеря стала
|
|
48
|
+
* `track_unseen`; появились `presenceChecks`, `heardWithoutTrack` и
|
|
49
|
+
* `evidence` у gap'ов.
|
|
50
|
+
*
|
|
51
|
+
* ВЫКАТКА v6: агент едет образом, api — своим релизом, и порядок не
|
|
52
|
+
* гарантирован. Новый агент шлёт причину `track_unseen`, которой у старого
|
|
53
|
+
* api нет в enum, — такой отчёт не разберётся целиком и станет `null`, то
|
|
54
|
+
* есть «данных нет». Это безопасная сторона (звук держим, ничего не удаляем),
|
|
55
|
+
* но api с этой схемой должен уехать НЕ ПОЗЖЕ образа агента. Ровно те же
|
|
56
|
+
* грабли были у `no_track` в TAS-511, см. api calls/audioReconcile.test.ts.
|
|
37
57
|
*
|
|
38
58
|
* ПРИ ЧТЕНИИ поля разбираются по одному, отсутствующие дают значение по
|
|
39
59
|
* умолчанию — агент и api выкатываются раздельно, и отчёт старого образа не
|
|
@@ -103,20 +123,31 @@ export declare const TranscriptCoverage: z.ZodObject<{
|
|
|
103
123
|
identity: string;
|
|
104
124
|
name?: string | undefined;
|
|
105
125
|
}>, "many">>;
|
|
106
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* Те, у кого речь могла потеряться. Список урезан, счётчик — нет.
|
|
128
|
+
*
|
|
129
|
+
* `evidence` (v6, TAS-536) — чем причина доказана, словами: «комната слышала
|
|
130
|
+
* его как говорящего (4)», «проверок присутствия: 20, публикаций не видели ни
|
|
131
|
+
* одной». Разбирать такой случай будут по одному отчёту, без доступа к логам
|
|
132
|
+
* того контейнера, а `track_unseen` без основания — это утверждение, которому
|
|
133
|
+
* нечем верить. Пусто у отчётов старее v6 и там, где причина однозначна.
|
|
134
|
+
*/
|
|
107
135
|
gaps: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
108
136
|
identity: z.ZodString;
|
|
109
137
|
name: z.ZodDefault<z.ZodString>;
|
|
110
138
|
} & {
|
|
111
|
-
reason: z.ZodEnum<["not_subscribed", "no_track", "no_audio", "suppressed"]>;
|
|
139
|
+
reason: z.ZodEnum<["not_subscribed", "track_unseen", "no_track", "no_audio", "suppressed"]>;
|
|
140
|
+
evidence: z.ZodDefault<z.ZodString>;
|
|
112
141
|
}, "strip", z.ZodTypeAny, {
|
|
113
142
|
identity: string;
|
|
114
143
|
name: string;
|
|
115
|
-
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed";
|
|
144
|
+
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed" | "track_unseen";
|
|
145
|
+
evidence: string;
|
|
116
146
|
}, {
|
|
117
147
|
identity: string;
|
|
118
148
|
name?: string | undefined;
|
|
119
|
-
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed";
|
|
149
|
+
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed" | "track_unseen";
|
|
150
|
+
evidence?: string | undefined;
|
|
120
151
|
}>, "many">>;
|
|
121
152
|
gapCount: z.ZodDefault<z.ZodNumber>;
|
|
122
153
|
/**
|
|
@@ -150,6 +181,30 @@ export declare const TranscriptCoverage: z.ZodObject<{
|
|
|
150
181
|
* дожимать было нечего — публикации от него нет вовсе.
|
|
151
182
|
*/
|
|
152
183
|
presenceProbes: z.ZodDefault<z.ZodNumber>;
|
|
184
|
+
/**
|
|
185
|
+
* А сколько раз сверка присутствия вообще СМОТРЕЛА на людей без дорожки
|
|
186
|
+
* (v6, TAS-536).
|
|
187
|
+
*
|
|
188
|
+
* Ровно то, чего не хватало при разборе дейли 18.08: в отчёте стояло
|
|
189
|
+
* `presenceProbes: 0` при восьми gap'ах `no_track`, и это прочли как «сверка
|
|
190
|
+
* не отработала ни разу». Отработала: флаг `no_track` ставит ТОЛЬКО она, то
|
|
191
|
+
* есть проходов было минимум восемь — просто дожимать было нечего, публикаций
|
|
192
|
+
* у этих людей агент не видел ни одной («дожали публикаций: 0» в логе).
|
|
193
|
+
*
|
|
194
|
+
* Ноль ЗДЕСЬ при непустых gap'ах — вот это уже поломка самой сверки, и она
|
|
195
|
+
* наконец отличима от «сверка работала, а дожимать нечего».
|
|
196
|
+
*/
|
|
197
|
+
presenceChecks: z.ZodDefault<z.ZodNumber>;
|
|
198
|
+
/**
|
|
199
|
+
* Скольких комната слышала как говорящих, а аудио-дорожки от них агент не
|
|
200
|
+
* видел (v6, TAS-536).
|
|
201
|
+
*
|
|
202
|
+
* Самое дорогое число в отчёте: больше нуля значит, что человек говорил, его
|
|
203
|
+
* слышали остальные, и мимо расшифровки прошла живая речь — не тишина, не
|
|
204
|
+
* режим слушателя. До v6 такой человек попадал в `no_track` вперемешку с
|
|
205
|
+
* теми, кто просто не включал микрофон, и потеря была невидима.
|
|
206
|
+
*/
|
|
207
|
+
heardWithoutTrack: z.ZodDefault<z.ZodNumber>;
|
|
153
208
|
/**
|
|
154
209
|
* Чем кончился выход джоба. `drain: "cancelled" | "abandoned"` означает, что
|
|
155
210
|
* хвост очереди распознавания не доехал до базы, — снаружи это выглядит как
|
|
@@ -269,7 +324,8 @@ export declare const TranscriptCoverage: z.ZodObject<{
|
|
|
269
324
|
gaps: {
|
|
270
325
|
identity: string;
|
|
271
326
|
name: string;
|
|
272
|
-
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed";
|
|
327
|
+
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed" | "track_unseen";
|
|
328
|
+
evidence: string;
|
|
273
329
|
}[];
|
|
274
330
|
gapCount: number;
|
|
275
331
|
repairedSubscriptions: number;
|
|
@@ -281,6 +337,8 @@ export declare const TranscriptCoverage: z.ZodObject<{
|
|
|
281
337
|
stuckCount: number;
|
|
282
338
|
suppressedSegments: number;
|
|
283
339
|
presenceProbes: number;
|
|
340
|
+
presenceChecks: number;
|
|
341
|
+
heardWithoutTrack: number;
|
|
284
342
|
shutdown: {
|
|
285
343
|
drain: "abandoned" | "cancelled" | "drained";
|
|
286
344
|
unfinishedRecorders: number;
|
|
@@ -323,7 +381,8 @@ export declare const TranscriptCoverage: z.ZodObject<{
|
|
|
323
381
|
gaps?: {
|
|
324
382
|
identity: string;
|
|
325
383
|
name?: string | undefined;
|
|
326
|
-
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed";
|
|
384
|
+
reason: "no_audio" | "no_track" | "not_subscribed" | "suppressed" | "track_unseen";
|
|
385
|
+
evidence?: string | undefined;
|
|
327
386
|
}[] | undefined;
|
|
328
387
|
gapCount?: number | undefined;
|
|
329
388
|
repairedSubscriptions?: number | undefined;
|
|
@@ -335,6 +394,8 @@ export declare const TranscriptCoverage: z.ZodObject<{
|
|
|
335
394
|
stuckCount?: number | undefined;
|
|
336
395
|
suppressedSegments?: number | undefined;
|
|
337
396
|
presenceProbes?: number | undefined;
|
|
397
|
+
presenceChecks?: number | undefined;
|
|
398
|
+
heardWithoutTrack?: number | undefined;
|
|
338
399
|
shutdown?: {
|
|
339
400
|
drain?: "abandoned" | "cancelled" | "drained" | undefined;
|
|
340
401
|
unfinishedRecorders?: number | undefined;
|
|
@@ -388,9 +449,91 @@ export declare function hasTranscriptCoverageGap(coverage: TranscriptCoverage |
|
|
|
388
449
|
* увидеть, не разбирая базу руками.
|
|
389
450
|
*/
|
|
390
451
|
export declare function transcriptCoverageSummary(coverage: TranscriptCoverage): string;
|
|
452
|
+
/**
|
|
453
|
+
* Те же цифры без головы фразы — «0 дорожек из 1 участника».
|
|
454
|
+
*
|
|
455
|
+
* Отдельно от `transcriptCoverageSummary`, потому что с PRJ3-109 эти цифры
|
|
456
|
+
* иногда приходится вставлять в другую фразу: когда отчёт покрывает не весь
|
|
457
|
+
* звонок, «Распознавали 0» в начале строки читается как приговор всей встрече.
|
|
458
|
+
*/
|
|
459
|
+
export declare function transcriptCoverageCounts(coverage: TranscriptCoverage): string;
|
|
391
460
|
/** «1 дорожку», «2 дорожки», «5 дорожек» — винительный, как в «распознавали N». */
|
|
392
461
|
export declare function pluralTracks(n: number): string;
|
|
393
462
|
/** «из 1 участника», «из 13 участников» — родительный, как в «из N». */
|
|
394
463
|
export declare function pluralPeople(n: number): string;
|
|
464
|
+
/** «1 человек», «2 человека», «13 человек» — именительный, как в «говорят N». */
|
|
465
|
+
export declare function pluralPersons(n: number): string;
|
|
466
|
+
/**
|
|
467
|
+
* Насколько окно отчёта может не дотягивать до границ звонка.
|
|
468
|
+
*
|
|
469
|
+
* Тот же допуск и по той же причине, что у сверки звука в api
|
|
470
|
+
* (`calls/audioReconcile.ts`): джоб диспатчится и финализируется не в ту же
|
|
471
|
+
* секунду, в которую началась и кончилась сессия, и держать из-за этих секунд
|
|
472
|
+
* пометку «отчёт не про весь звонок» значит показывать её всегда. Минута —
|
|
473
|
+
* заведомо больше этой разницы и заведомо меньше перезапуска джоба, ради
|
|
474
|
+
* которого пометка и заводится.
|
|
475
|
+
*/
|
|
476
|
+
export declare const COVERAGE_WINDOW_SLACK_MS = 60000;
|
|
477
|
+
/** Кто и сколько наговорил по базе (`CallTranscript` этой сессии) — ФАКТ, с
|
|
478
|
+
* которым сверяется отчёт агента. */
|
|
479
|
+
export interface TranscriptSpeakerFact {
|
|
480
|
+
/** userId говорящего; null у гостей — у них `speakerId` в базе пуст. */
|
|
481
|
+
id: string | null;
|
|
482
|
+
name: string;
|
|
483
|
+
lines: number;
|
|
484
|
+
}
|
|
485
|
+
export interface TranscriptCoverageContext {
|
|
486
|
+
/**
|
|
487
|
+
* Границы ЗВОНКА (сессии), с которыми сверяется окно отчёта. `to: null` —
|
|
488
|
+
* сессия ещё идёт.
|
|
489
|
+
*/
|
|
490
|
+
callSpan?: {
|
|
491
|
+
from: string | Date;
|
|
492
|
+
to?: string | Date | null;
|
|
493
|
+
} | null;
|
|
494
|
+
/** Факт из базы: кто попал в расшифровку. `null`/`undefined` — факта нет,
|
|
495
|
+
* и тогда отчёт остаётся единственным источником. */
|
|
496
|
+
speakers?: TranscriptSpeakerFact[] | null;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Что на самом деле известно про покрытие — семантика без копирайта.
|
|
500
|
+
*
|
|
501
|
+
* PRJ3-109. Отчёт агента описывает ОКНО ДЖОБА, а страница читала его как итог
|
|
502
|
+
* по звонку: на часовом созвоне с 800 репликами и тринадцатью говорящими висело
|
|
503
|
+
* «Распознавали 0 дорожек из 1 участника» — отчёт хвостового джоба, который
|
|
504
|
+
* успел увидеть одного человека. Здесь мы отвечаем на три вопроса, а словами их
|
|
505
|
+
* называет интерфейс (`TranscriptCoverageNotice`):
|
|
506
|
+
*
|
|
507
|
+
* 1. покрывает ли отчёт весь звонок (`coversCall`);
|
|
508
|
+
* 2. не разошёлся ли он с базой (`underReported`) — в сессии остаётся ПОСЛЕДНИЙ
|
|
509
|
+
* отчёт, а не сумма, поэтому вклад умерших джобов из цифр исчезает;
|
|
510
|
+
* 3. какие дыры фактом уже сняты (`resolvedGapCount`) — человек, у которого в
|
|
511
|
+
* расшифровке 238 реплик, потерянным не является, чей бы отчёт его так ни
|
|
512
|
+
* называл.
|
|
513
|
+
*/
|
|
514
|
+
export interface TranscriptCoverageReading {
|
|
515
|
+
/** Покрывает ли отчёт звонок целиком. `null` — сверить не с чем: окна нет
|
|
516
|
+
* (агент старее v5) либо границы звонка не переданы. */
|
|
517
|
+
coversCall: boolean | null;
|
|
518
|
+
/** Отрезок, за который отчёт отвечает. */
|
|
519
|
+
window: {
|
|
520
|
+
from: Date;
|
|
521
|
+
to: Date;
|
|
522
|
+
} | null;
|
|
523
|
+
/** Сколько человек реально попало в расшифровку. `null` — факта нет. */
|
|
524
|
+
transcriptSpeakers: number | null;
|
|
525
|
+
/** Отчёт насчитал меньше дорожек, чем в базе говоривших: цифры описывают не
|
|
526
|
+
* весь звонок. Это расхождение ОТЧЁТА С ДАННЫМИ, а не потеря текста. */
|
|
527
|
+
underReported: boolean;
|
|
528
|
+
/** Дыры, которые фактом не сняты, — в том же порядке, что в отчёте. */
|
|
529
|
+
gaps: TranscriptCoverage["gaps"];
|
|
530
|
+
/** Счётчик дыр за вычетом снятых (у отчёта он бывает больше списка). */
|
|
531
|
+
gapCount: number;
|
|
532
|
+
/** Сколько дыр сняла база: эти люди в расшифровке говорят. */
|
|
533
|
+
resolvedGapCount: number;
|
|
534
|
+
/** Есть ли о чём предупреждать после сверки с фактом. */
|
|
535
|
+
hasGap: boolean;
|
|
536
|
+
}
|
|
537
|
+
export declare function transcriptCoverageReading(coverage: TranscriptCoverage, ctx?: TranscriptCoverageContext): TranscriptCoverageReading;
|
|
395
538
|
/** Человеческая причина провала — одними словами в UI и в логах. */
|
|
396
539
|
export declare const TRANSCRIPT_COVERAGE_GAP_LABEL: Record<TranscriptCoverageGapReason, string>;
|
|
@@ -19,20 +19,31 @@ import { z } from "zod";
|
|
|
19
19
|
* знает, была ли подписка и шли ли PCM-кадры; здесь мы её читаем.
|
|
20
20
|
*
|
|
21
21
|
* `not_subscribed` — публиковал аудио, а рекордера на дорожке не было ни разу;
|
|
22
|
+
* `track_unseen` — дорожка БЫЛА, а агент её не увидел (v6, TAS-536). Доказано
|
|
23
|
+
* одним из двух: комната называла человека активным
|
|
24
|
+
* говорящим (это считает SFU по звуку публикующей стороны и
|
|
25
|
+
* рассылает всем — мимо наших подписок), либо у него висели
|
|
26
|
+
* неподписанные публикации. Дейли 18.08: Дмитрий Гребенев
|
|
27
|
+
* отвечал 102 секунды, его слышали все, Сергей поблагодарил
|
|
28
|
+
* по имени — а в отчёте он «аудио не публиковал»;
|
|
22
29
|
* `no_track` — аудио не публиковал ВОВСЕ, но просидел в комнате дольше
|
|
23
30
|
* порога сверки присутствия (пять минут). Про этих людей до
|
|
24
31
|
* TAS-511 отчёт говорил «слушатель»: Дима Гальянов, 39 минут
|
|
25
|
-
* в звонке, ноль реплик — и ни строки о нём в логе
|
|
32
|
+
* в звонке, ноль реплик — и ни строки о нём в логе агента.
|
|
33
|
+
* С v6 это ровно «микрофон не включали»: признаков дорожки
|
|
34
|
+
* нет ни одного, и раньше сюда же уезжала потеря;
|
|
26
35
|
* `no_audio` — подписка была, но ни одного кадра не доехало;
|
|
27
36
|
* `suppressed` — сегменты распознавались, но их выбрасывал анти-дубль
|
|
28
37
|
* «участник вышел» (собственно баг PRJ3-101).
|
|
29
38
|
*
|
|
30
39
|
* Молчавших и слушателей здесь НЕТ: их ноль объяснён, и сигналом он не
|
|
31
|
-
* является — иначе предупреждение висело бы на каждом созвоне.
|
|
32
|
-
*
|
|
40
|
+
* является — иначе предупреждение висело бы на каждом созвоне. Границу между
|
|
41
|
+
* «слушал» и «не слышали» проводит время в комнате, а границу между «не
|
|
42
|
+
* включал микрофон» и «не увидели дорожку» — доказательство, а не время.
|
|
33
43
|
*/
|
|
34
44
|
export const TranscriptCoverageGapReason = z.enum([
|
|
35
45
|
"not_subscribed",
|
|
46
|
+
"track_unseen",
|
|
36
47
|
"no_track",
|
|
37
48
|
"no_audio",
|
|
38
49
|
"suppressed",
|
|
@@ -56,7 +67,17 @@ export const TranscriptCoverage = z.object({
|
|
|
56
67
|
* комнате дольше пяти минут без единой дорожки, теперь gap с причиной
|
|
57
68
|
* `no_track`, а не слушатель; v4 (TAS-509) — появился `audioStall`;
|
|
58
69
|
* v5 (TAS-524) — появились `window` и `jobId`: отчёт наконец говорит, за
|
|
59
|
-
* какой отрезок он
|
|
70
|
+
* какой отрезок он отвечает; v6 (TAS-536) — `no_track` разошёлся надвое:
|
|
71
|
+
* «микрофон не включали» остался `no_track`, а доказанная потеря стала
|
|
72
|
+
* `track_unseen`; появились `presenceChecks`, `heardWithoutTrack` и
|
|
73
|
+
* `evidence` у gap'ов.
|
|
74
|
+
*
|
|
75
|
+
* ВЫКАТКА v6: агент едет образом, api — своим релизом, и порядок не
|
|
76
|
+
* гарантирован. Новый агент шлёт причину `track_unseen`, которой у старого
|
|
77
|
+
* api нет в enum, — такой отчёт не разберётся целиком и станет `null`, то
|
|
78
|
+
* есть «данных нет». Это безопасная сторона (звук держим, ничего не удаляем),
|
|
79
|
+
* но api с этой схемой должен уехать НЕ ПОЗЖЕ образа агента. Ровно те же
|
|
80
|
+
* грабли были у `no_track` в TAS-511, см. api calls/audioReconcile.test.ts.
|
|
60
81
|
*
|
|
61
82
|
* ПРИ ЧТЕНИИ поля разбираются по одному, отсутствующие дают значение по
|
|
62
83
|
* умолчанию — агент и api выкатываются раздельно, и отчёт старого образа не
|
|
@@ -105,8 +126,21 @@ export const TranscriptCoverage = z.object({
|
|
|
105
126
|
silent: z.array(Person).default([]),
|
|
106
127
|
/** Аудио не публиковал вовсе — слушатель, ноль реплик ожидаем. */
|
|
107
128
|
listeners: z.array(Person).default([]),
|
|
108
|
-
/**
|
|
109
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Те, у кого речь могла потеряться. Список урезан, счётчик — нет.
|
|
131
|
+
*
|
|
132
|
+
* `evidence` (v6, TAS-536) — чем причина доказана, словами: «комната слышала
|
|
133
|
+
* его как говорящего (4)», «проверок присутствия: 20, публикаций не видели ни
|
|
134
|
+
* одной». Разбирать такой случай будут по одному отчёту, без доступа к логам
|
|
135
|
+
* того контейнера, а `track_unseen` без основания — это утверждение, которому
|
|
136
|
+
* нечем верить. Пусто у отчётов старее v6 и там, где причина однозначна.
|
|
137
|
+
*/
|
|
138
|
+
gaps: z
|
|
139
|
+
.array(Person.extend({
|
|
140
|
+
reason: TranscriptCoverageGapReason,
|
|
141
|
+
evidence: z.string().default(""),
|
|
142
|
+
}))
|
|
143
|
+
.default([]),
|
|
110
144
|
gapCount: z.number().int().min(0).default(0),
|
|
111
145
|
/**
|
|
112
146
|
* Сколько дорожек реконсиляция починила ПО-НАСТОЯЩЕМУ: дожала подписку, и
|
|
@@ -130,6 +164,30 @@ export const TranscriptCoverage = z.object({
|
|
|
130
164
|
* дожимать было нечего — публикации от него нет вовсе.
|
|
131
165
|
*/
|
|
132
166
|
presenceProbes: z.number().int().min(0).default(0),
|
|
167
|
+
/**
|
|
168
|
+
* А сколько раз сверка присутствия вообще СМОТРЕЛА на людей без дорожки
|
|
169
|
+
* (v6, TAS-536).
|
|
170
|
+
*
|
|
171
|
+
* Ровно то, чего не хватало при разборе дейли 18.08: в отчёте стояло
|
|
172
|
+
* `presenceProbes: 0` при восьми gap'ах `no_track`, и это прочли как «сверка
|
|
173
|
+
* не отработала ни разу». Отработала: флаг `no_track` ставит ТОЛЬКО она, то
|
|
174
|
+
* есть проходов было минимум восемь — просто дожимать было нечего, публикаций
|
|
175
|
+
* у этих людей агент не видел ни одной («дожали публикаций: 0» в логе).
|
|
176
|
+
*
|
|
177
|
+
* Ноль ЗДЕСЬ при непустых gap'ах — вот это уже поломка самой сверки, и она
|
|
178
|
+
* наконец отличима от «сверка работала, а дожимать нечего».
|
|
179
|
+
*/
|
|
180
|
+
presenceChecks: z.number().int().min(0).default(0),
|
|
181
|
+
/**
|
|
182
|
+
* Скольких комната слышала как говорящих, а аудио-дорожки от них агент не
|
|
183
|
+
* видел (v6, TAS-536).
|
|
184
|
+
*
|
|
185
|
+
* Самое дорогое число в отчёте: больше нуля значит, что человек говорил, его
|
|
186
|
+
* слышали остальные, и мимо расшифровки прошла живая речь — не тишина, не
|
|
187
|
+
* режим слушателя. До v6 такой человек попадал в `no_track` вперемешку с
|
|
188
|
+
* теми, кто просто не включал микрофон, и потеря была невидима.
|
|
189
|
+
*/
|
|
190
|
+
heardWithoutTrack: z.number().int().min(0).default(0),
|
|
133
191
|
/**
|
|
134
192
|
* Чем кончился выход джоба. `drain: "cancelled" | "abandoned"` означает, что
|
|
135
193
|
* хвост очереди распознавания не доехал до базы, — снаружи это выглядит как
|
|
@@ -218,7 +276,17 @@ export function hasTranscriptCoverageGap(coverage) {
|
|
|
218
276
|
* увидеть, не разбирая базу руками.
|
|
219
277
|
*/
|
|
220
278
|
export function transcriptCoverageSummary(coverage) {
|
|
221
|
-
return `Распознавали ${
|
|
279
|
+
return `Распознавали ${transcriptCoverageCounts(coverage)}`;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Те же цифры без головы фразы — «0 дорожек из 1 участника».
|
|
283
|
+
*
|
|
284
|
+
* Отдельно от `transcriptCoverageSummary`, потому что с PRJ3-109 эти цифры
|
|
285
|
+
* иногда приходится вставлять в другую фразу: когда отчёт покрывает не весь
|
|
286
|
+
* звонок, «Распознавали 0» в начале строки читается как приговор всей встрече.
|
|
287
|
+
*/
|
|
288
|
+
export function transcriptCoverageCounts(coverage) {
|
|
289
|
+
return `${coverage.recognized} ${pluralTracks(coverage.recognized)} из ${coverage.participants} ${pluralPeople(coverage.participants)}`;
|
|
222
290
|
}
|
|
223
291
|
function plural(n, one, few, many) {
|
|
224
292
|
const mod100 = n % 100;
|
|
@@ -239,9 +307,78 @@ export function pluralTracks(n) {
|
|
|
239
307
|
export function pluralPeople(n) {
|
|
240
308
|
return plural(n, "участника", "участников", "участников");
|
|
241
309
|
}
|
|
310
|
+
/** «1 человек», «2 человека», «13 человек» — именительный, как в «говорят N». */
|
|
311
|
+
export function pluralPersons(n) {
|
|
312
|
+
return plural(n, "человек", "человека", "человек");
|
|
313
|
+
}
|
|
314
|
+
// ─── PRJ3-109: отчёт за окно джоба ≠ итог по звонку ──────────────────────
|
|
315
|
+
/**
|
|
316
|
+
* Насколько окно отчёта может не дотягивать до границ звонка.
|
|
317
|
+
*
|
|
318
|
+
* Тот же допуск и по той же причине, что у сверки звука в api
|
|
319
|
+
* (`calls/audioReconcile.ts`): джоб диспатчится и финализируется не в ту же
|
|
320
|
+
* секунду, в которую началась и кончилась сессия, и держать из-за этих секунд
|
|
321
|
+
* пометку «отчёт не про весь звонок» значит показывать её всегда. Минута —
|
|
322
|
+
* заведомо больше этой разницы и заведомо меньше перезапуска джоба, ради
|
|
323
|
+
* которого пометка и заводится.
|
|
324
|
+
*/
|
|
325
|
+
export const COVERAGE_WINDOW_SLACK_MS = 60_000;
|
|
326
|
+
export function transcriptCoverageReading(coverage, ctx = {}) {
|
|
327
|
+
const window = transcriptCoverageWindow(coverage);
|
|
328
|
+
const speakers = ctx.speakers ?? null;
|
|
329
|
+
const spoke = speakers ? speakers.filter((s) => s.lines > 0) : null;
|
|
330
|
+
// Сняты те дыры, у кого в базе есть реплики. Сверяем по userId: identity
|
|
331
|
+
// участника-мембера в LiveKit — это и есть его userId, а `speakerId` в
|
|
332
|
+
// `CallTranscript` — он же. Гость (identity `guest_*`, speakerId пуст) так не
|
|
333
|
+
// сверяется — по имени сверять нельзя, тёзки и переименования дают ложное
|
|
334
|
+
// «всё хорошо», а цена ошибки здесь — спрятанная потеря речи.
|
|
335
|
+
const spokeIds = new Set((spoke ?? []).map((s) => s.id).filter((id) => !!id));
|
|
336
|
+
const gaps = spokeIds.size > 0
|
|
337
|
+
? coverage.gaps.filter((g) => !spokeIds.has(g.identity))
|
|
338
|
+
: coverage.gaps;
|
|
339
|
+
const resolvedGapCount = coverage.gaps.length - gaps.length;
|
|
340
|
+
const gapCount = Math.max(0, coverage.gapCount - resolvedGapCount);
|
|
341
|
+
return {
|
|
342
|
+
coversCall: windowCoversCall(window, ctx.callSpan ?? null),
|
|
343
|
+
window,
|
|
344
|
+
transcriptSpeakers: spoke ? spoke.length : null,
|
|
345
|
+
underReported: !!spoke && spoke.length > coverage.recognized,
|
|
346
|
+
gaps,
|
|
347
|
+
gapCount,
|
|
348
|
+
resolvedGapCount,
|
|
349
|
+
hasGap: gapCount > 0,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Покрывает ли окно отчёта весь звонок.
|
|
354
|
+
*
|
|
355
|
+
* У живой сессии (`to` не задан) сверяем ТОЛЬКО начало: конец отчёта у идущего
|
|
356
|
+
* звонка всегда в прошлом — джоб пишет отчёт на переоткрытии сессии, — и
|
|
357
|
+
* сверка по концу означала бы вечное «отчёт не про весь звонок» на каждом
|
|
358
|
+
* здоровом созвоне. А вот отчёт, начавшийся заметно позже начала звонка, — это
|
|
359
|
+
* ровно тот перезапуск джоба, ради которого всё написано.
|
|
360
|
+
*/
|
|
361
|
+
function windowCoversCall(window, span) {
|
|
362
|
+
if (!window || !span)
|
|
363
|
+
return null;
|
|
364
|
+
const from = new Date(span.from);
|
|
365
|
+
if (Number.isNaN(from.getTime()))
|
|
366
|
+
return null;
|
|
367
|
+
if (window.from.getTime() - COVERAGE_WINDOW_SLACK_MS > from.getTime())
|
|
368
|
+
return false;
|
|
369
|
+
if (span.to === null || span.to === undefined)
|
|
370
|
+
return true;
|
|
371
|
+
const to = new Date(span.to);
|
|
372
|
+
if (Number.isNaN(to.getTime()))
|
|
373
|
+
return null;
|
|
374
|
+
return window.to.getTime() + COVERAGE_WINDOW_SLACK_MS >= to.getTime();
|
|
375
|
+
}
|
|
242
376
|
/** Человеческая причина провала — одними словами в UI и в логах. */
|
|
243
377
|
export const TRANSCRIPT_COVERAGE_GAP_LABEL = {
|
|
244
378
|
not_subscribed: "дорожку не слушали",
|
|
379
|
+
// TAS-536: два соседних ярлыка — это и есть развод причин. Первый читается
|
|
380
|
+
// как потеря («его слышали, а мы нет»), второй — как объяснимый ноль.
|
|
381
|
+
track_unseen: "его слышали в звонке, а дорожку мы не увидели",
|
|
245
382
|
no_track: "дорожки от него не было",
|
|
246
383
|
no_audio: "звук не доехал",
|
|
247
384
|
suppressed: "речь распозналась, но не записалась",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcriptCoverage.js","sourceRoot":"","sources":["../src/transcriptCoverage.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,4EAA4E;AAC5E,oDAAoD;AACpD,EAAE;AACF,gEAAgE;AAChE,+EAA+E;AAC/E,2EAA2E;AAC3E,0EAA0E;AAC1E,EAAE;AACF,4EAA4E;AAC5E,iEAAiE;AAEjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB
|
|
1
|
+
{"version":3,"file":"transcriptCoverage.js","sourceRoot":"","sources":["../src/transcriptCoverage.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskless-app/shared",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared types, Zod schemas and design tokens for the Taskless API contract — consumed by @taskless/api, @taskless/web and the Taskless mobile app.",
|
|
6
6
|
"license": "MIT",
|