evo360-types 1.3.530 → 1.3.532
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/apps/evo-chat/chatbee/zod-schemas.d.ts +16 -16
- package/dist/types/evo-chat/channel/index.d.ts +3 -0
- package/dist/types/evo-chat/channel/index.ts +3 -0
- package/dist/types/evo-chat/index.d.ts +1 -0
- package/dist/types/evo-chat/index.js +1 -0
- package/dist/types/evo-chat/index.ts +1 -0
- package/dist/types/evo-chat/waba-history-import.d.ts +263 -0
- package/dist/types/evo-chat/waba-history-import.js +59 -0
- package/dist/types/evo-chat/waba-history-import.ts +285 -0
- package/package.json +1 -1
|
@@ -484,27 +484,27 @@ export declare const zTemplateHeaderMediaSchema: z.ZodEffects<z.ZodObject<{
|
|
|
484
484
|
}, "strip", z.ZodTypeAny, {
|
|
485
485
|
type: "image" | "video" | "document";
|
|
486
486
|
link?: string | undefined;
|
|
487
|
-
gcs_uri?: string | undefined;
|
|
488
487
|
mime_type?: string | undefined;
|
|
489
488
|
filename?: string | undefined;
|
|
489
|
+
gcs_uri?: string | undefined;
|
|
490
490
|
}, {
|
|
491
491
|
type: "image" | "video" | "document";
|
|
492
492
|
link?: string | undefined;
|
|
493
|
-
gcs_uri?: string | undefined;
|
|
494
493
|
mime_type?: string | undefined;
|
|
495
494
|
filename?: string | undefined;
|
|
495
|
+
gcs_uri?: string | undefined;
|
|
496
496
|
}>, {
|
|
497
497
|
type: "image" | "video" | "document";
|
|
498
498
|
link?: string | undefined;
|
|
499
|
-
gcs_uri?: string | undefined;
|
|
500
499
|
mime_type?: string | undefined;
|
|
501
500
|
filename?: string | undefined;
|
|
501
|
+
gcs_uri?: string | undefined;
|
|
502
502
|
}, {
|
|
503
503
|
type: "image" | "video" | "document";
|
|
504
504
|
link?: string | undefined;
|
|
505
|
-
gcs_uri?: string | undefined;
|
|
506
505
|
mime_type?: string | undefined;
|
|
507
506
|
filename?: string | undefined;
|
|
507
|
+
gcs_uri?: string | undefined;
|
|
508
508
|
}>;
|
|
509
509
|
/**
|
|
510
510
|
* Schema para requisição de envio de mensagem de texto
|
|
@@ -576,27 +576,27 @@ export declare const zSendTemplateMessageRequestSchema: z.ZodObject<{
|
|
|
576
576
|
}, "strip", z.ZodTypeAny, {
|
|
577
577
|
type: "image" | "video" | "document";
|
|
578
578
|
link?: string | undefined;
|
|
579
|
-
gcs_uri?: string | undefined;
|
|
580
579
|
mime_type?: string | undefined;
|
|
581
580
|
filename?: string | undefined;
|
|
581
|
+
gcs_uri?: string | undefined;
|
|
582
582
|
}, {
|
|
583
583
|
type: "image" | "video" | "document";
|
|
584
584
|
link?: string | undefined;
|
|
585
|
-
gcs_uri?: string | undefined;
|
|
586
585
|
mime_type?: string | undefined;
|
|
587
586
|
filename?: string | undefined;
|
|
587
|
+
gcs_uri?: string | undefined;
|
|
588
588
|
}>, {
|
|
589
589
|
type: "image" | "video" | "document";
|
|
590
590
|
link?: string | undefined;
|
|
591
|
-
gcs_uri?: string | undefined;
|
|
592
591
|
mime_type?: string | undefined;
|
|
593
592
|
filename?: string | undefined;
|
|
593
|
+
gcs_uri?: string | undefined;
|
|
594
594
|
}, {
|
|
595
595
|
type: "image" | "video" | "document";
|
|
596
596
|
link?: string | undefined;
|
|
597
|
-
gcs_uri?: string | undefined;
|
|
598
597
|
mime_type?: string | undefined;
|
|
599
598
|
filename?: string | undefined;
|
|
599
|
+
gcs_uri?: string | undefined;
|
|
600
600
|
}>>;
|
|
601
601
|
button_payloads: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
602
602
|
index: z.ZodNumber;
|
|
@@ -629,9 +629,9 @@ export declare const zSendTemplateMessageRequestSchema: z.ZodObject<{
|
|
|
629
629
|
header_media?: {
|
|
630
630
|
type: "image" | "video" | "document";
|
|
631
631
|
link?: string | undefined;
|
|
632
|
-
gcs_uri?: string | undefined;
|
|
633
632
|
mime_type?: string | undefined;
|
|
634
633
|
filename?: string | undefined;
|
|
634
|
+
gcs_uri?: string | undefined;
|
|
635
635
|
} | undefined;
|
|
636
636
|
button_payloads?: {
|
|
637
637
|
index: number;
|
|
@@ -658,9 +658,9 @@ export declare const zSendTemplateMessageRequestSchema: z.ZodObject<{
|
|
|
658
658
|
header_media?: {
|
|
659
659
|
type: "image" | "video" | "document";
|
|
660
660
|
link?: string | undefined;
|
|
661
|
-
gcs_uri?: string | undefined;
|
|
662
661
|
mime_type?: string | undefined;
|
|
663
662
|
filename?: string | undefined;
|
|
663
|
+
gcs_uri?: string | undefined;
|
|
664
664
|
} | undefined;
|
|
665
665
|
button_payloads?: {
|
|
666
666
|
index: number;
|
|
@@ -733,27 +733,27 @@ export declare const zSendMessageRequestSchema: z.ZodDiscriminatedUnion<"type",
|
|
|
733
733
|
}, "strip", z.ZodTypeAny, {
|
|
734
734
|
type: "image" | "video" | "document";
|
|
735
735
|
link?: string | undefined;
|
|
736
|
-
gcs_uri?: string | undefined;
|
|
737
736
|
mime_type?: string | undefined;
|
|
738
737
|
filename?: string | undefined;
|
|
738
|
+
gcs_uri?: string | undefined;
|
|
739
739
|
}, {
|
|
740
740
|
type: "image" | "video" | "document";
|
|
741
741
|
link?: string | undefined;
|
|
742
|
-
gcs_uri?: string | undefined;
|
|
743
742
|
mime_type?: string | undefined;
|
|
744
743
|
filename?: string | undefined;
|
|
744
|
+
gcs_uri?: string | undefined;
|
|
745
745
|
}>, {
|
|
746
746
|
type: "image" | "video" | "document";
|
|
747
747
|
link?: string | undefined;
|
|
748
|
-
gcs_uri?: string | undefined;
|
|
749
748
|
mime_type?: string | undefined;
|
|
750
749
|
filename?: string | undefined;
|
|
750
|
+
gcs_uri?: string | undefined;
|
|
751
751
|
}, {
|
|
752
752
|
type: "image" | "video" | "document";
|
|
753
753
|
link?: string | undefined;
|
|
754
|
-
gcs_uri?: string | undefined;
|
|
755
754
|
mime_type?: string | undefined;
|
|
756
755
|
filename?: string | undefined;
|
|
756
|
+
gcs_uri?: string | undefined;
|
|
757
757
|
}>>;
|
|
758
758
|
button_payloads: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
759
759
|
index: z.ZodNumber;
|
|
@@ -786,9 +786,9 @@ export declare const zSendMessageRequestSchema: z.ZodDiscriminatedUnion<"type",
|
|
|
786
786
|
header_media?: {
|
|
787
787
|
type: "image" | "video" | "document";
|
|
788
788
|
link?: string | undefined;
|
|
789
|
-
gcs_uri?: string | undefined;
|
|
790
789
|
mime_type?: string | undefined;
|
|
791
790
|
filename?: string | undefined;
|
|
791
|
+
gcs_uri?: string | undefined;
|
|
792
792
|
} | undefined;
|
|
793
793
|
button_payloads?: {
|
|
794
794
|
index: number;
|
|
@@ -815,9 +815,9 @@ export declare const zSendMessageRequestSchema: z.ZodDiscriminatedUnion<"type",
|
|
|
815
815
|
header_media?: {
|
|
816
816
|
type: "image" | "video" | "document";
|
|
817
817
|
link?: string | undefined;
|
|
818
|
-
gcs_uri?: string | undefined;
|
|
819
818
|
mime_type?: string | undefined;
|
|
820
819
|
filename?: string | undefined;
|
|
820
|
+
gcs_uri?: string | undefined;
|
|
821
821
|
} | undefined;
|
|
822
822
|
button_payloads?: {
|
|
823
823
|
index: number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IHubIAConfig } from "../../evo-hub-ia/channel";
|
|
2
2
|
import { IFireDoc } from "../../shared";
|
|
3
|
+
import type { IChannelHistoryImport } from "../waba-history-import";
|
|
3
4
|
export type ChannelProvider = 'chatbee' | 'hub-waba' | 'hub-instagram';
|
|
4
5
|
export type ChannelType = 'waba' | 'instagram' | 'telegram' | 'email' | 'sms';
|
|
5
6
|
export type ChannelStatus = 'active' | 'paused' | 'disabled' | 'pending';
|
|
@@ -60,5 +61,7 @@ export interface IChannel extends IFireDoc {
|
|
|
60
61
|
provider_ref: IChannelProviderRef;
|
|
61
62
|
hub_ia?: IHubIAConfig;
|
|
62
63
|
calls?: ICallsChannelConfig;
|
|
64
|
+
/** feat-142 — rollup da recepção do histórico de coexistência (WABA). */
|
|
65
|
+
history_import?: IChannelHistoryImport;
|
|
63
66
|
[key: string]: unknown;
|
|
64
67
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IHubIAConfig } from "../../evo-hub-ia/channel";
|
|
2
2
|
import { IFireDoc } from "../../shared";
|
|
3
|
+
import type { IChannelHistoryImport } from "../waba-history-import";
|
|
3
4
|
|
|
4
5
|
// ── Channel provider/type enums ──
|
|
5
6
|
|
|
@@ -84,5 +85,7 @@ export interface IChannel extends IFireDoc {
|
|
|
84
85
|
provider_ref: IChannelProviderRef;
|
|
85
86
|
hub_ia?: IHubIAConfig;
|
|
86
87
|
calls?: ICallsChannelConfig;
|
|
88
|
+
/** feat-142 — rollup da recepção do histórico de coexistência (WABA). */
|
|
89
|
+
history_import?: IChannelHistoryImport;
|
|
87
90
|
[key: string]: unknown;
|
|
88
91
|
}
|
|
@@ -27,6 +27,7 @@ __exportStar(require("./ticket"), exports);
|
|
|
27
27
|
__exportStar(require("./inbox"), exports);
|
|
28
28
|
__exportStar(require("./waba-template"), exports);
|
|
29
29
|
__exportStar(require("./waba-setup"), exports);
|
|
30
|
+
__exportStar(require("./waba-history-import"), exports);
|
|
30
31
|
__exportStar(require("./ig-setup"), exports);
|
|
31
32
|
__exportStar(require("./quick-reply"), exports);
|
|
32
33
|
__exportStar(require("./search"), exports);
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { IFireDoc } from "../shared";
|
|
3
|
+
/**
|
|
4
|
+
* feat-142 — importação sob demanda do histórico de coexistência WABA.
|
|
5
|
+
*
|
|
6
|
+
* A recepção (Fase 1) só acumula os chunks no staging e o rollup do canal
|
|
7
|
+
* (`IChannelHistoryImport`) + o manifest de mídia (`IWabaHistoryMediaManifest`).
|
|
8
|
+
* A materialização (contatos/threads/mensagens/tickets/leads) acontece depois,
|
|
9
|
+
* sob demanda, num job (`IWabaHistoryImportJob`) disparado pelo admin.
|
|
10
|
+
*/
|
|
11
|
+
export declare const WABA_HISTORY_IMPORT_PUBSUB_TOPIC: "app_hub-waba_history-import_request";
|
|
12
|
+
/**
|
|
13
|
+
* Subcoleção dos jobs, sob o canal:
|
|
14
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-import-jobs/{jobId}`
|
|
15
|
+
*/
|
|
16
|
+
export declare const WABA_HISTORY_IMPORT_JOBS_COLLECTION: "history-import-jobs";
|
|
17
|
+
/**
|
|
18
|
+
* Subcoleção do manifest de mídia, sob o canal, com `{wamid}` como id do doc:
|
|
19
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-media/{wamid}`
|
|
20
|
+
*/
|
|
21
|
+
export declare const WABA_HISTORY_MEDIA_COLLECTION: "history-media";
|
|
22
|
+
/** Janela padrão quando o operador não escolhe nada. */
|
|
23
|
+
export declare const WABA_HISTORY_IMPORT_DEFAULT_WINDOW_MONTHS: 3;
|
|
24
|
+
/** Janela de importação: tudo, últimos N meses, ou a partir de uma data. */
|
|
25
|
+
export type WabaHistoryImportWindowMode = "all" | "months" | "since";
|
|
26
|
+
/** 'dry_run' = conta sem escrever; 'execute' = importa de verdade. */
|
|
27
|
+
export type WabaHistoryImportJobMode = "dry_run" | "execute";
|
|
28
|
+
export type WabaHistoryImportJobStatus = "pending" | "running" | "done" | "failed";
|
|
29
|
+
/**
|
|
30
|
+
* Rollup do canal: 'receiving' enquanto chegam chunks, 'completed' com
|
|
31
|
+
* progress 100, 'declined' quando a Meta recusa o compartilhamento (2593109).
|
|
32
|
+
*/
|
|
33
|
+
export type ChannelHistoryImportStatus = "receiving" | "completed" | "declined";
|
|
34
|
+
/** Situação do download de um asset no manifest. */
|
|
35
|
+
export type WabaHistoryMediaStatus = "stored" | "failed" | "unavailable";
|
|
36
|
+
export interface IWabaHistoryImportWindow {
|
|
37
|
+
mode: WabaHistoryImportWindowMode;
|
|
38
|
+
/** Obrigatório quando `mode === 'months'`. */
|
|
39
|
+
months?: number;
|
|
40
|
+
/** Data ISO (corte inferior). Obrigatório quando `mode === 'since'`. */
|
|
41
|
+
since?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface IWabaHistoryImportConfig {
|
|
44
|
+
window: IWabaHistoryImportWindow;
|
|
45
|
+
/** Departamento de destino dos tickets históricos (fechados). */
|
|
46
|
+
department_id: string;
|
|
47
|
+
/**
|
|
48
|
+
* D10 — opt-in de transcrição. Default false. Só enfileira áudios com
|
|
49
|
+
* manifest `stored` dentro da janela e sem transcrição prévia.
|
|
50
|
+
*/
|
|
51
|
+
transcribe_audios: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Cursor keyset sobre o staging dos chunks, ordenado por
|
|
55
|
+
* (received_at, trace_id, fragment_index). A página seguinte retoma
|
|
56
|
+
* estritamente APÓS esta tupla; `null` = começa do início.
|
|
57
|
+
*/
|
|
58
|
+
export interface IWabaHistoryImportCursor {
|
|
59
|
+
/** `received_at` do último fragmento processado, em ISO 8601. */
|
|
60
|
+
received_at: string;
|
|
61
|
+
trace_id: string;
|
|
62
|
+
fragment_index: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Totais acumulados por página, para a UI acompanhar o progresso e a
|
|
66
|
+
* continuação (republish com cursor) retomar contagem consistente.
|
|
67
|
+
*/
|
|
68
|
+
export interface IWabaHistoryImportCounters {
|
|
69
|
+
/** Fragmentos lidos do staging. */
|
|
70
|
+
rows_read: number;
|
|
71
|
+
threads: number;
|
|
72
|
+
messages_imported: number;
|
|
73
|
+
messages_skipped_dup: number;
|
|
74
|
+
/** Mensagens descartadas por estarem fora da janela configurada. */
|
|
75
|
+
messages_out_of_window: number;
|
|
76
|
+
contacts_touched: number;
|
|
77
|
+
leads_published: number;
|
|
78
|
+
tickets_closed: number;
|
|
79
|
+
/** Mensagens de mídia casadas com um manifest `stored`. */
|
|
80
|
+
media_linked: number;
|
|
81
|
+
/** Mensagens de mídia sem manifest utilizável (viram `unsupported`). */
|
|
82
|
+
media_unavailable: number;
|
|
83
|
+
/** Total de placeholders de mídia vistos — denominador da cobertura. */
|
|
84
|
+
media_placeholders_total: number;
|
|
85
|
+
/** D10 — áudios elegíveis a transcrição (manifest `stored`, sem transcript). */
|
|
86
|
+
audios_transcribable: number;
|
|
87
|
+
/** D10 — eventos de transcrição efetivamente publicados. */
|
|
88
|
+
audio_transcriptions_queued: number;
|
|
89
|
+
}
|
|
90
|
+
export interface IWabaHistoryImportRequestedBy {
|
|
91
|
+
user_id: string;
|
|
92
|
+
login_id: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Doc do job em
|
|
96
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-import-jobs/{jobId}`.
|
|
97
|
+
*/
|
|
98
|
+
export interface IWabaHistoryImportJob extends IFireDoc {
|
|
99
|
+
channel_id: string;
|
|
100
|
+
mode: WabaHistoryImportJobMode;
|
|
101
|
+
status: WabaHistoryImportJobStatus;
|
|
102
|
+
config: IWabaHistoryImportConfig;
|
|
103
|
+
/** Cursor da última página commitada; null antes da primeira. */
|
|
104
|
+
cursor: IWabaHistoryImportCursor | null;
|
|
105
|
+
counters: IWabaHistoryImportCounters;
|
|
106
|
+
requested_by: IWabaHistoryImportRequestedBy;
|
|
107
|
+
error: string | null;
|
|
108
|
+
created_at: Date | null;
|
|
109
|
+
updated_at: Date | null;
|
|
110
|
+
started_at?: Date | null;
|
|
111
|
+
finished_at?: Date | null;
|
|
112
|
+
}
|
|
113
|
+
/** Ids devolvidos pela Meta ao pedir o compartilhamento (`smb_app_data`). */
|
|
114
|
+
export interface IChannelHistoryImportRequestIds {
|
|
115
|
+
history_request_id?: string | null;
|
|
116
|
+
state_sync_request_id?: string | null;
|
|
117
|
+
}
|
|
118
|
+
/** Estado do pedido de sync disparado no onboarding (G1). */
|
|
119
|
+
export interface IChannelHistoryImportSync {
|
|
120
|
+
requested_at?: Date | null;
|
|
121
|
+
request_ids?: IChannelHistoryImportRequestIds;
|
|
122
|
+
last_error?: string | null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Rollup da recepção, gravado no doc do canal em `history_import`.
|
|
126
|
+
* Contadores são incrementais (`FieldValue.increment`) — aproximados sob
|
|
127
|
+
* redelivery; o número exato vive no BQ.
|
|
128
|
+
*/
|
|
129
|
+
export interface IChannelHistoryImport {
|
|
130
|
+
status: ChannelHistoryImportStatus;
|
|
131
|
+
/** false quando a Meta recusou o compartilhamento (erro 2593109). */
|
|
132
|
+
history_shared?: boolean;
|
|
133
|
+
/** Pedido de sync (history + smb_app_state_sync) feito no onboarding. */
|
|
134
|
+
sync?: IChannelHistoryImportSync;
|
|
135
|
+
chunks_received: number;
|
|
136
|
+
messages_received: number;
|
|
137
|
+
threads_seen: number;
|
|
138
|
+
/** Contatos vistos nos chunks de `smb_app_state_sync`. */
|
|
139
|
+
contacts_received: number;
|
|
140
|
+
/** Placeholders de mídia vistos nos chunks (denominador da cobertura). */
|
|
141
|
+
media_placeholders_seen: number;
|
|
142
|
+
/** Assets de mídia recebidos na raiz do payload e passados ao harvester. */
|
|
143
|
+
media_assets_received: number;
|
|
144
|
+
/** Subconjunto de `media_assets_received` do tipo áudio (D10 — UI pré-dry-run). */
|
|
145
|
+
audio_assets_received: number;
|
|
146
|
+
/** Maior `progress` visto (monotônico, 0..100). */
|
|
147
|
+
max_progress: number;
|
|
148
|
+
/** `phase` do último chunk recebido. */
|
|
149
|
+
last_phase?: number | null;
|
|
150
|
+
last_chunk_at?: Date | null;
|
|
151
|
+
/** Último chunk de `smb_app_state_sync` processado. */
|
|
152
|
+
last_state_sync_at?: Date | null;
|
|
153
|
+
/** Momento da recusa (2593109). */
|
|
154
|
+
declined_at?: Date | null;
|
|
155
|
+
/** Preenchido quando o progress chega a 100. */
|
|
156
|
+
completed_at?: Date | null;
|
|
157
|
+
}
|
|
158
|
+
/** Direção da mensagem que carregava o asset. */
|
|
159
|
+
export type WabaHistoryMediaDirection = "in" | "out";
|
|
160
|
+
/**
|
|
161
|
+
* Doc do manifest de mídia em
|
|
162
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-media/{wamid}`
|
|
163
|
+
* (id do doc = `wamid`). Escrito na recepção (G3) e consultado pelo motor
|
|
164
|
+
* para fundir a mídia na mensagem materializada.
|
|
165
|
+
*/
|
|
166
|
+
export interface IWabaHistoryMediaManifest extends IFireDoc {
|
|
167
|
+
wamid: string;
|
|
168
|
+
/** `media.id` usado no download via Graph. */
|
|
169
|
+
media_id: string;
|
|
170
|
+
/** Outros `media.id` vistos para o mesmo wamid (reentrega/duplicata). */
|
|
171
|
+
dup_media_ids: string[];
|
|
172
|
+
/** Tipo da mensagem de origem: 'image' | 'audio' | 'video' | 'document' | … */
|
|
173
|
+
msg_type: string;
|
|
174
|
+
direction: WabaHistoryMediaDirection;
|
|
175
|
+
/** Timestamp da mensagem em epoch segundos (como o normalizer entrega). */
|
|
176
|
+
timestamp: number;
|
|
177
|
+
mime_type?: string | null;
|
|
178
|
+
filename?: string | null;
|
|
179
|
+
caption?: string | null;
|
|
180
|
+
/** sha256 como a Meta entrega (base64). */
|
|
181
|
+
sha256_b64?: string | null;
|
|
182
|
+
/** sha256 do objeto baixado, em hex (conferido contra `sha256_b64`). */
|
|
183
|
+
sha256_hex?: string | null;
|
|
184
|
+
size_bytes?: number | null;
|
|
185
|
+
/** `gs://…` do objeto no bucket do hub-waba; null se não armazenado. */
|
|
186
|
+
gcs_uri?: string | null;
|
|
187
|
+
status: WabaHistoryMediaStatus;
|
|
188
|
+
error?: string | null;
|
|
189
|
+
downloaded_at?: Date | null;
|
|
190
|
+
}
|
|
191
|
+
export declare const WabaHistoryImportWindowSchema: z.ZodEffects<z.ZodObject<{
|
|
192
|
+
mode: z.ZodEnum<["all", "months", "since"]>;
|
|
193
|
+
months: z.ZodOptional<z.ZodNumber>;
|
|
194
|
+
since: z.ZodOptional<z.ZodString>;
|
|
195
|
+
}, "strip", z.ZodTypeAny, {
|
|
196
|
+
mode: "all" | "months" | "since";
|
|
197
|
+
months?: number | undefined;
|
|
198
|
+
since?: string | undefined;
|
|
199
|
+
}, {
|
|
200
|
+
mode: "all" | "months" | "since";
|
|
201
|
+
months?: number | undefined;
|
|
202
|
+
since?: string | undefined;
|
|
203
|
+
}>, {
|
|
204
|
+
mode: "all" | "months" | "since";
|
|
205
|
+
months?: number | undefined;
|
|
206
|
+
since?: string | undefined;
|
|
207
|
+
}, {
|
|
208
|
+
mode: "all" | "months" | "since";
|
|
209
|
+
months?: number | undefined;
|
|
210
|
+
since?: string | undefined;
|
|
211
|
+
}>;
|
|
212
|
+
/** Body de POST …/history-import/dry-run e …/history-import/execute. */
|
|
213
|
+
export declare const WabaHistoryImportRequestSchema: z.ZodObject<{
|
|
214
|
+
window: z.ZodDefault<z.ZodEffects<z.ZodObject<{
|
|
215
|
+
mode: z.ZodEnum<["all", "months", "since"]>;
|
|
216
|
+
months: z.ZodOptional<z.ZodNumber>;
|
|
217
|
+
since: z.ZodOptional<z.ZodString>;
|
|
218
|
+
}, "strip", z.ZodTypeAny, {
|
|
219
|
+
mode: "all" | "months" | "since";
|
|
220
|
+
months?: number | undefined;
|
|
221
|
+
since?: string | undefined;
|
|
222
|
+
}, {
|
|
223
|
+
mode: "all" | "months" | "since";
|
|
224
|
+
months?: number | undefined;
|
|
225
|
+
since?: string | undefined;
|
|
226
|
+
}>, {
|
|
227
|
+
mode: "all" | "months" | "since";
|
|
228
|
+
months?: number | undefined;
|
|
229
|
+
since?: string | undefined;
|
|
230
|
+
}, {
|
|
231
|
+
mode: "all" | "months" | "since";
|
|
232
|
+
months?: number | undefined;
|
|
233
|
+
since?: string | undefined;
|
|
234
|
+
}>>;
|
|
235
|
+
department_id: z.ZodString;
|
|
236
|
+
/** D10 — opt-in; ausente = false (comportamento de hoje). */
|
|
237
|
+
transcribe_audios: z.ZodDefault<z.ZodBoolean>;
|
|
238
|
+
}, "strip", z.ZodTypeAny, {
|
|
239
|
+
window: {
|
|
240
|
+
mode: "all" | "months" | "since";
|
|
241
|
+
months?: number | undefined;
|
|
242
|
+
since?: string | undefined;
|
|
243
|
+
};
|
|
244
|
+
department_id: string;
|
|
245
|
+
transcribe_audios: boolean;
|
|
246
|
+
}, {
|
|
247
|
+
department_id: string;
|
|
248
|
+
window?: {
|
|
249
|
+
mode: "all" | "months" | "since";
|
|
250
|
+
months?: number | undefined;
|
|
251
|
+
since?: string | undefined;
|
|
252
|
+
} | undefined;
|
|
253
|
+
transcribe_audios?: boolean | undefined;
|
|
254
|
+
}>;
|
|
255
|
+
export type IWabaHistoryImportRequestPayload = z.infer<typeof WabaHistoryImportRequestSchema>;
|
|
256
|
+
export interface IWabaHistoryImportPubSubEvent {
|
|
257
|
+
tenant: string;
|
|
258
|
+
channelId: string;
|
|
259
|
+
jobId: string;
|
|
260
|
+
/** Cursor para retomar numa continuação; null/ausente na primeira execução. */
|
|
261
|
+
cursor?: IWabaHistoryImportCursor | null;
|
|
262
|
+
trace_id?: string;
|
|
263
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WabaHistoryImportRequestSchema = exports.WabaHistoryImportWindowSchema = exports.WABA_HISTORY_IMPORT_DEFAULT_WINDOW_MONTHS = exports.WABA_HISTORY_MEDIA_COLLECTION = exports.WABA_HISTORY_IMPORT_JOBS_COLLECTION = exports.WABA_HISTORY_IMPORT_PUBSUB_TOPIC = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/**
|
|
6
|
+
* feat-142 — importação sob demanda do histórico de coexistência WABA.
|
|
7
|
+
*
|
|
8
|
+
* A recepção (Fase 1) só acumula os chunks no staging e o rollup do canal
|
|
9
|
+
* (`IChannelHistoryImport`) + o manifest de mídia (`IWabaHistoryMediaManifest`).
|
|
10
|
+
* A materialização (contatos/threads/mensagens/tickets/leads) acontece depois,
|
|
11
|
+
* sob demanda, num job (`IWabaHistoryImportJob`) disparado pelo admin.
|
|
12
|
+
*/
|
|
13
|
+
// ── Constants ──
|
|
14
|
+
exports.WABA_HISTORY_IMPORT_PUBSUB_TOPIC = "app_hub-waba_history-import_request";
|
|
15
|
+
/**
|
|
16
|
+
* Subcoleção dos jobs, sob o canal:
|
|
17
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-import-jobs/{jobId}`
|
|
18
|
+
*/
|
|
19
|
+
exports.WABA_HISTORY_IMPORT_JOBS_COLLECTION = "history-import-jobs";
|
|
20
|
+
/**
|
|
21
|
+
* Subcoleção do manifest de mídia, sob o canal, com `{wamid}` como id do doc:
|
|
22
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-media/{wamid}`
|
|
23
|
+
*/
|
|
24
|
+
exports.WABA_HISTORY_MEDIA_COLLECTION = "history-media";
|
|
25
|
+
/** Janela padrão quando o operador não escolhe nada. */
|
|
26
|
+
exports.WABA_HISTORY_IMPORT_DEFAULT_WINDOW_MONTHS = 3;
|
|
27
|
+
// ── Zod Schemas (body dos endpoints admin) ──
|
|
28
|
+
exports.WabaHistoryImportWindowSchema = zod_1.z
|
|
29
|
+
.object({
|
|
30
|
+
mode: zod_1.z.enum(["all", "months", "since"]),
|
|
31
|
+
months: zod_1.z.number().int().positive().optional(),
|
|
32
|
+
since: zod_1.z.string().min(1).optional(),
|
|
33
|
+
})
|
|
34
|
+
.superRefine((w, ctx) => {
|
|
35
|
+
if (w.mode === "months" && w.months === undefined) {
|
|
36
|
+
ctx.addIssue({
|
|
37
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
38
|
+
path: ["months"],
|
|
39
|
+
message: "months é obrigatório quando mode = 'months'",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (w.mode === "since" && !w.since) {
|
|
43
|
+
ctx.addIssue({
|
|
44
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
45
|
+
path: ["since"],
|
|
46
|
+
message: "since é obrigatório quando mode = 'since'",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
/** Body de POST …/history-import/dry-run e …/history-import/execute. */
|
|
51
|
+
exports.WabaHistoryImportRequestSchema = zod_1.z.object({
|
|
52
|
+
window: exports.WabaHistoryImportWindowSchema.default({
|
|
53
|
+
mode: "months",
|
|
54
|
+
months: exports.WABA_HISTORY_IMPORT_DEFAULT_WINDOW_MONTHS,
|
|
55
|
+
}),
|
|
56
|
+
department_id: zod_1.z.string().min(1),
|
|
57
|
+
/** D10 — opt-in; ausente = false (comportamento de hoje). */
|
|
58
|
+
transcribe_audios: zod_1.z.boolean().default(false),
|
|
59
|
+
});
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { IFireDoc } from "../shared";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* feat-142 — importação sob demanda do histórico de coexistência WABA.
|
|
6
|
+
*
|
|
7
|
+
* A recepção (Fase 1) só acumula os chunks no staging e o rollup do canal
|
|
8
|
+
* (`IChannelHistoryImport`) + o manifest de mídia (`IWabaHistoryMediaManifest`).
|
|
9
|
+
* A materialização (contatos/threads/mensagens/tickets/leads) acontece depois,
|
|
10
|
+
* sob demanda, num job (`IWabaHistoryImportJob`) disparado pelo admin.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ── Constants ──
|
|
14
|
+
|
|
15
|
+
export const WABA_HISTORY_IMPORT_PUBSUB_TOPIC =
|
|
16
|
+
"app_hub-waba_history-import_request" as const;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Subcoleção dos jobs, sob o canal:
|
|
20
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-import-jobs/{jobId}`
|
|
21
|
+
*/
|
|
22
|
+
export const WABA_HISTORY_IMPORT_JOBS_COLLECTION =
|
|
23
|
+
"history-import-jobs" as const;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Subcoleção do manifest de mídia, sob o canal, com `{wamid}` como id do doc:
|
|
27
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-media/{wamid}`
|
|
28
|
+
*/
|
|
29
|
+
export const WABA_HISTORY_MEDIA_COLLECTION = "history-media" as const;
|
|
30
|
+
|
|
31
|
+
/** Janela padrão quando o operador não escolhe nada. */
|
|
32
|
+
export const WABA_HISTORY_IMPORT_DEFAULT_WINDOW_MONTHS = 3 as const;
|
|
33
|
+
|
|
34
|
+
// ── Enums / Literals ──
|
|
35
|
+
|
|
36
|
+
/** Janela de importação: tudo, últimos N meses, ou a partir de uma data. */
|
|
37
|
+
export type WabaHistoryImportWindowMode = "all" | "months" | "since";
|
|
38
|
+
|
|
39
|
+
/** 'dry_run' = conta sem escrever; 'execute' = importa de verdade. */
|
|
40
|
+
export type WabaHistoryImportJobMode = "dry_run" | "execute";
|
|
41
|
+
|
|
42
|
+
export type WabaHistoryImportJobStatus =
|
|
43
|
+
| "pending"
|
|
44
|
+
| "running"
|
|
45
|
+
| "done"
|
|
46
|
+
| "failed";
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Rollup do canal: 'receiving' enquanto chegam chunks, 'completed' com
|
|
50
|
+
* progress 100, 'declined' quando a Meta recusa o compartilhamento (2593109).
|
|
51
|
+
*/
|
|
52
|
+
export type ChannelHistoryImportStatus =
|
|
53
|
+
| "receiving"
|
|
54
|
+
| "completed"
|
|
55
|
+
| "declined";
|
|
56
|
+
|
|
57
|
+
/** Situação do download de um asset no manifest. */
|
|
58
|
+
export type WabaHistoryMediaStatus = "stored" | "failed" | "unavailable";
|
|
59
|
+
|
|
60
|
+
// ── Config / Window ──
|
|
61
|
+
|
|
62
|
+
export interface IWabaHistoryImportWindow {
|
|
63
|
+
mode: WabaHistoryImportWindowMode;
|
|
64
|
+
/** Obrigatório quando `mode === 'months'`. */
|
|
65
|
+
months?: number;
|
|
66
|
+
/** Data ISO (corte inferior). Obrigatório quando `mode === 'since'`. */
|
|
67
|
+
since?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface IWabaHistoryImportConfig {
|
|
71
|
+
window: IWabaHistoryImportWindow;
|
|
72
|
+
/** Departamento de destino dos tickets históricos (fechados). */
|
|
73
|
+
department_id: string;
|
|
74
|
+
/**
|
|
75
|
+
* D10 — opt-in de transcrição. Default false. Só enfileira áudios com
|
|
76
|
+
* manifest `stored` dentro da janela e sem transcrição prévia.
|
|
77
|
+
*/
|
|
78
|
+
transcribe_audios: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── Job sub-interfaces ──
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Cursor keyset sobre o staging dos chunks, ordenado por
|
|
85
|
+
* (received_at, trace_id, fragment_index). A página seguinte retoma
|
|
86
|
+
* estritamente APÓS esta tupla; `null` = começa do início.
|
|
87
|
+
*/
|
|
88
|
+
export interface IWabaHistoryImportCursor {
|
|
89
|
+
/** `received_at` do último fragmento processado, em ISO 8601. */
|
|
90
|
+
received_at: string;
|
|
91
|
+
trace_id: string;
|
|
92
|
+
fragment_index: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Totais acumulados por página, para a UI acompanhar o progresso e a
|
|
97
|
+
* continuação (republish com cursor) retomar contagem consistente.
|
|
98
|
+
*/
|
|
99
|
+
export interface IWabaHistoryImportCounters {
|
|
100
|
+
/** Fragmentos lidos do staging. */
|
|
101
|
+
rows_read: number;
|
|
102
|
+
threads: number;
|
|
103
|
+
messages_imported: number;
|
|
104
|
+
messages_skipped_dup: number;
|
|
105
|
+
/** Mensagens descartadas por estarem fora da janela configurada. */
|
|
106
|
+
messages_out_of_window: number;
|
|
107
|
+
contacts_touched: number;
|
|
108
|
+
leads_published: number;
|
|
109
|
+
tickets_closed: number;
|
|
110
|
+
/** Mensagens de mídia casadas com um manifest `stored`. */
|
|
111
|
+
media_linked: number;
|
|
112
|
+
/** Mensagens de mídia sem manifest utilizável (viram `unsupported`). */
|
|
113
|
+
media_unavailable: number;
|
|
114
|
+
/** Total de placeholders de mídia vistos — denominador da cobertura. */
|
|
115
|
+
media_placeholders_total: number;
|
|
116
|
+
/** D10 — áudios elegíveis a transcrição (manifest `stored`, sem transcript). */
|
|
117
|
+
audios_transcribable: number;
|
|
118
|
+
/** D10 — eventos de transcrição efetivamente publicados. */
|
|
119
|
+
audio_transcriptions_queued: number;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface IWabaHistoryImportRequestedBy {
|
|
123
|
+
user_id: string;
|
|
124
|
+
login_id: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ── Job Document ──
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Doc do job em
|
|
131
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-import-jobs/{jobId}`.
|
|
132
|
+
*/
|
|
133
|
+
export interface IWabaHistoryImportJob extends IFireDoc {
|
|
134
|
+
channel_id: string;
|
|
135
|
+
mode: WabaHistoryImportJobMode;
|
|
136
|
+
status: WabaHistoryImportJobStatus;
|
|
137
|
+
config: IWabaHistoryImportConfig;
|
|
138
|
+
/** Cursor da última página commitada; null antes da primeira. */
|
|
139
|
+
cursor: IWabaHistoryImportCursor | null;
|
|
140
|
+
counters: IWabaHistoryImportCounters;
|
|
141
|
+
requested_by: IWabaHistoryImportRequestedBy;
|
|
142
|
+
error: string | null;
|
|
143
|
+
created_at: Date | null;
|
|
144
|
+
updated_at: Date | null;
|
|
145
|
+
started_at?: Date | null;
|
|
146
|
+
finished_at?: Date | null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ── Channel rollup ──
|
|
150
|
+
|
|
151
|
+
/** Ids devolvidos pela Meta ao pedir o compartilhamento (`smb_app_data`). */
|
|
152
|
+
export interface IChannelHistoryImportRequestIds {
|
|
153
|
+
history_request_id?: string | null;
|
|
154
|
+
state_sync_request_id?: string | null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Estado do pedido de sync disparado no onboarding (G1). */
|
|
158
|
+
export interface IChannelHistoryImportSync {
|
|
159
|
+
requested_at?: Date | null;
|
|
160
|
+
request_ids?: IChannelHistoryImportRequestIds;
|
|
161
|
+
last_error?: string | null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Rollup da recepção, gravado no doc do canal em `history_import`.
|
|
166
|
+
* Contadores são incrementais (`FieldValue.increment`) — aproximados sob
|
|
167
|
+
* redelivery; o número exato vive no BQ.
|
|
168
|
+
*/
|
|
169
|
+
export interface IChannelHistoryImport {
|
|
170
|
+
status: ChannelHistoryImportStatus;
|
|
171
|
+
/** false quando a Meta recusou o compartilhamento (erro 2593109). */
|
|
172
|
+
history_shared?: boolean;
|
|
173
|
+
/** Pedido de sync (history + smb_app_state_sync) feito no onboarding. */
|
|
174
|
+
sync?: IChannelHistoryImportSync;
|
|
175
|
+
chunks_received: number;
|
|
176
|
+
messages_received: number;
|
|
177
|
+
threads_seen: number;
|
|
178
|
+
/** Contatos vistos nos chunks de `smb_app_state_sync`. */
|
|
179
|
+
contacts_received: number;
|
|
180
|
+
/** Placeholders de mídia vistos nos chunks (denominador da cobertura). */
|
|
181
|
+
media_placeholders_seen: number;
|
|
182
|
+
/** Assets de mídia recebidos na raiz do payload e passados ao harvester. */
|
|
183
|
+
media_assets_received: number;
|
|
184
|
+
/** Subconjunto de `media_assets_received` do tipo áudio (D10 — UI pré-dry-run). */
|
|
185
|
+
audio_assets_received: number;
|
|
186
|
+
/** Maior `progress` visto (monotônico, 0..100). */
|
|
187
|
+
max_progress: number;
|
|
188
|
+
/** `phase` do último chunk recebido. */
|
|
189
|
+
last_phase?: number | null;
|
|
190
|
+
last_chunk_at?: Date | null;
|
|
191
|
+
/** Último chunk de `smb_app_state_sync` processado. */
|
|
192
|
+
last_state_sync_at?: Date | null;
|
|
193
|
+
/** Momento da recusa (2593109). */
|
|
194
|
+
declined_at?: Date | null;
|
|
195
|
+
/** Preenchido quando o progress chega a 100. */
|
|
196
|
+
completed_at?: Date | null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ── Media manifest ──
|
|
200
|
+
|
|
201
|
+
/** Direção da mensagem que carregava o asset. */
|
|
202
|
+
export type WabaHistoryMediaDirection = "in" | "out";
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Doc do manifest de mídia em
|
|
206
|
+
* `tenants/{tenant}/apps/evo-chat/channels/{channelId}/history-media/{wamid}`
|
|
207
|
+
* (id do doc = `wamid`). Escrito na recepção (G3) e consultado pelo motor
|
|
208
|
+
* para fundir a mídia na mensagem materializada.
|
|
209
|
+
*/
|
|
210
|
+
export interface IWabaHistoryMediaManifest extends IFireDoc {
|
|
211
|
+
wamid: string;
|
|
212
|
+
/** `media.id` usado no download via Graph. */
|
|
213
|
+
media_id: string;
|
|
214
|
+
/** Outros `media.id` vistos para o mesmo wamid (reentrega/duplicata). */
|
|
215
|
+
dup_media_ids: string[];
|
|
216
|
+
/** Tipo da mensagem de origem: 'image' | 'audio' | 'video' | 'document' | … */
|
|
217
|
+
msg_type: string;
|
|
218
|
+
direction: WabaHistoryMediaDirection;
|
|
219
|
+
/** Timestamp da mensagem em epoch segundos (como o normalizer entrega). */
|
|
220
|
+
timestamp: number;
|
|
221
|
+
mime_type?: string | null;
|
|
222
|
+
filename?: string | null;
|
|
223
|
+
caption?: string | null;
|
|
224
|
+
/** sha256 como a Meta entrega (base64). */
|
|
225
|
+
sha256_b64?: string | null;
|
|
226
|
+
/** sha256 do objeto baixado, em hex (conferido contra `sha256_b64`). */
|
|
227
|
+
sha256_hex?: string | null;
|
|
228
|
+
size_bytes?: number | null;
|
|
229
|
+
/** `gs://…` do objeto no bucket do hub-waba; null se não armazenado. */
|
|
230
|
+
gcs_uri?: string | null;
|
|
231
|
+
status: WabaHistoryMediaStatus;
|
|
232
|
+
error?: string | null;
|
|
233
|
+
downloaded_at?: Date | null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ── Zod Schemas (body dos endpoints admin) ──
|
|
237
|
+
|
|
238
|
+
export const WabaHistoryImportWindowSchema = z
|
|
239
|
+
.object({
|
|
240
|
+
mode: z.enum(["all", "months", "since"]),
|
|
241
|
+
months: z.number().int().positive().optional(),
|
|
242
|
+
since: z.string().min(1).optional(),
|
|
243
|
+
})
|
|
244
|
+
.superRefine((w, ctx) => {
|
|
245
|
+
if (w.mode === "months" && w.months === undefined) {
|
|
246
|
+
ctx.addIssue({
|
|
247
|
+
code: z.ZodIssueCode.custom,
|
|
248
|
+
path: ["months"],
|
|
249
|
+
message: "months é obrigatório quando mode = 'months'",
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
if (w.mode === "since" && !w.since) {
|
|
253
|
+
ctx.addIssue({
|
|
254
|
+
code: z.ZodIssueCode.custom,
|
|
255
|
+
path: ["since"],
|
|
256
|
+
message: "since é obrigatório quando mode = 'since'",
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
/** Body de POST …/history-import/dry-run e …/history-import/execute. */
|
|
262
|
+
export const WabaHistoryImportRequestSchema = z.object({
|
|
263
|
+
window: WabaHistoryImportWindowSchema.default({
|
|
264
|
+
mode: "months",
|
|
265
|
+
months: WABA_HISTORY_IMPORT_DEFAULT_WINDOW_MONTHS,
|
|
266
|
+
}),
|
|
267
|
+
department_id: z.string().min(1),
|
|
268
|
+
/** D10 — opt-in; ausente = false (comportamento de hoje). */
|
|
269
|
+
transcribe_audios: z.boolean().default(false),
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
export type IWabaHistoryImportRequestPayload = z.infer<
|
|
273
|
+
typeof WabaHistoryImportRequestSchema
|
|
274
|
+
>;
|
|
275
|
+
|
|
276
|
+
// ── PubSub Event ──
|
|
277
|
+
|
|
278
|
+
export interface IWabaHistoryImportPubSubEvent {
|
|
279
|
+
tenant: string;
|
|
280
|
+
channelId: string;
|
|
281
|
+
jobId: string;
|
|
282
|
+
/** Cursor para retomar numa continuação; null/ausente na primeira execução. */
|
|
283
|
+
cursor?: IWabaHistoryImportCursor | null;
|
|
284
|
+
trace_id?: string;
|
|
285
|
+
}
|