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.
@@ -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
  }
@@ -10,6 +10,7 @@ export * from "./ticket";
10
10
  export * from "./inbox";
11
11
  export * from "./waba-template";
12
12
  export * from "./waba-setup";
13
+ export * from "./waba-history-import";
13
14
  export * from "./ig-setup";
14
15
  export * from "./quick-reply";
15
16
  export * from "./search";
@@ -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);
@@ -10,6 +10,7 @@ export * from "./ticket";
10
10
  export * from "./inbox";
11
11
  export * from "./waba-template";
12
12
  export * from "./waba-setup";
13
+ export * from "./waba-history-import";
13
14
  export * from "./ig-setup";
14
15
  export * from "./quick-reply";
15
16
  export * from "./search";
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evo360-types",
3
- "version": "1.3.530",
3
+ "version": "1.3.532",
4
4
  "description": "HREVO360 Shared Types",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",