@adatechnology/meta-whatsapp-module 0.2.0-rc.2 → 0.2.0-rc.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/index.cjs +1408 -106
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1778 -240
  4. package/dist/index.d.ts +1778 -240
  5. package/dist/index.js +1368 -92
  6. package/dist/index.js.map +1 -1
  7. package/dist/migrations/0004_widen_message_type.sql +1 -0
  8. package/dist/migrations/0005_message_moderation.sql +3 -0
  9. package/dist/migrations/0006_conversation_documents.sql +19 -0
  10. package/dist/migrations/0007_flow_media.sql +18 -0
  11. package/dist/migrations/0008_message_transcription.sql +5 -0
  12. package/dist/migrations/0009_settings_transcription_policy.sql +2 -0
  13. package/dist/migrations/meta/_journal.json +76 -0
  14. package/dist/testing/index.cjs +222 -0
  15. package/dist/testing/index.cjs.map +1 -0
  16. package/dist/testing/index.d.cts +74 -0
  17. package/dist/testing/index.d.ts +74 -0
  18. package/dist/testing/index.js +186 -0
  19. package/dist/testing/index.js.map +1 -0
  20. package/package.json +23 -8
  21. package/dist/migrations/20260725195853_freezing_switch/snapshot.json +0 -555
  22. package/dist/migrations/20260725210958_military_leper_queen/snapshot.json +0 -742
  23. package/dist/migrations/20260725214800_illegal_black_tarantula/snapshot.json +0 -810
  24. package/dist/migrations/20260725234507_normal_viper/snapshot.json +0 -930
  25. /package/dist/migrations/{20260725195853_freezing_switch/migration.sql → 0000_freezing_switch.sql} +0 -0
  26. /package/dist/migrations/{20260725210958_military_leper_queen/migration.sql → 0001_military_leper_queen.sql} +0 -0
  27. /package/dist/migrations/{20260725214800_illegal_black_tarantula/migration.sql → 0002_illegal_black_tarantula.sql} +0 -0
  28. /package/dist/migrations/{20260725234507_normal_viper/migration.sql → 0003_normal_viper.sql} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,34 +1,109 @@
1
- import { BunSQLDatabase } from 'drizzle-orm/bun-sql/postgres';
2
- import { AnyRelations, EmptyRelations } from 'drizzle-orm/relations';
3
- import * as _adatechnology_meta_whatsapp_contracts from '@adatechnology/meta-whatsapp-contracts';
4
- import { SessionState, SessionMode, ConversationSummary, FlowGraphData, FlowGraphSummary, LiveFlowPosition, WhatsAppSettings, MessageDirection, MessageSender, MessageStatus, RealtimeNotifierInterface, ChannelAdapterInterface, ObjectStorageInterface, FlowActionKind, FlowActionHandler, ConversationSession, MetaWhatsAppHooks, SubjectResolverInterface, CatalogPort } from '@adatechnology/meta-whatsapp-contracts';
5
1
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
+ import { PgDatabase, PgQueryResultHKT } from 'drizzle-orm/pg-core';
3
+ import * as _adatechnology_meta_whatsapp_contracts from '@adatechnology/meta-whatsapp-contracts';
4
+ import { TranscriptionMode, SessionState, SessionMode, ConversationSummary, MessageDirection, MessageSender, MessageStatus, CacheInterface, FlowGraphData, FlowGraphSummary, LiveFlowPosition, WhatsAppSettings, RealtimeNotifierInterface, ChannelAdapterInterface, ObjectStorageInterface, FlowActionKind, FlowActionHandler, ConversationSession, MetaWhatsAppHooks, SubjectResolverInterface, CatalogPort } from '@adatechnology/meta-whatsapp-contracts';
5
+ export { PREVIEW_MEDIA_ID_PREFIX, TranscriptionMode, resolvePreviewUploadId, toPreviewMediaId } from '@adatechnology/meta-whatsapp-contracts';
6
6
  import { WhatsAppMessageProvider } from '@adatechnology/meta-whatsapp-provider';
7
7
 
8
+ type MetaWhatsAppDatabase = PgDatabase<PgQueryResultHKT, any, any>;
9
+ type DrizzleMigrateFunction = (db: never, config: {
10
+ migrationsFolder: string;
11
+ migrationsTable?: string;
12
+ }) => Promise<void>;
13
+
14
+ /**
15
+ * Vocabulário de transcrição de áudio do módulo.
16
+ *
17
+ * Fica em arquivo próprio porque o schema e os dois use-cases (ingestão automática e sob demanda)
18
+ * precisam dos mesmos tipos, e pendurá-los em qualquer um dos três faria os outros dois importarem
19
+ * de dentro de uma camada que não é a deles.
20
+ */
21
+
22
+ declare const TRANSCRIPTION_STATUS: {
23
+ /** Falhou de forma retriável (cota, rede, 5xx) — vai sair quando alguém tentar de novo. */
24
+ readonly PENDING: "pending";
25
+ /** Processado. Texto vazio aqui é áudio em silêncio, e NÃO deve ser reprocessado. */
26
+ readonly DONE: "done";
27
+ /** Falha definitiva do engine (credencial, áudio corrompido, arquivo grande demais). */
28
+ readonly FAILED: "failed";
29
+ /** Nenhum engine da cadeia aceita o formato. Retentar não conserta codec. */
30
+ readonly UNSUPPORTED: "unsupported";
31
+ };
32
+ type TranscriptionStatus = (typeof TRANSCRIPTION_STATUS)[keyof typeof TRANSCRIPTION_STATUS];
33
+ /**
34
+ * Quando transcrever.
35
+ *
36
+ * `auto` transcreve durante a ingestão da mídia, onde o buffer do áudio JÁ está em memória — não
37
+ * custa um segundo download do storage. `onDemand` só transcreve quando o atendente pede, o que
38
+ * troca latência na interface por não gastar cota com áudio que ninguém vai ler.
39
+ *
40
+ * O tipo vem do contrato (o painel escolhe, a API transporta, o módulo obedece) e `satisfies`
41
+ * garante em tempo de compilação que estes valores continuam sendo exatamente os de lá — sem isso,
42
+ * um modo novo no contrato passaria despercebido aqui.
43
+ */
44
+ declare const TRANSCRIPTION_MODE: {
45
+ readonly AUTO: "auto";
46
+ readonly ON_DEMAND: "onDemand";
47
+ };
48
+
49
+ /**
50
+ * O contrato mínimo de `@adatechnology/audio-transcription-provider`, declarado aqui em vez de
51
+ * importado — mesma decisão do `MessageModerator` em `LogMessage.use-case.ts`.
52
+ *
53
+ * Assim o módulo não ganha dependência de pacote por um recurso opcional, e transcrição não fica
54
+ * amarrada a WhatsApp: o que atravessa esta fronteira é um buffer de áudio e um mime.
55
+ */
56
+ type AudioTranscriber = {
57
+ readonly name: string;
58
+ transcribe: (input: {
59
+ buffer: Buffer;
60
+ mimeType: string;
61
+ languageHint?: string;
62
+ }) => Promise<{
63
+ text: string;
64
+ language?: string;
65
+ durationSeconds?: number;
66
+ engine: string;
67
+ }>;
68
+ };
69
+ /**
70
+ * Recorte do erro do provider que o módulo precisa ler para escolher entre `'pending'` e
71
+ * `'failed'`. Estrutural, não `instanceof`: o provider é opcional e pode nem estar instalado, e um
72
+ * `instanceof` contra classe ausente não compila.
73
+ */
74
+ declare function isRetriableTranscriptionError(error: unknown): boolean;
75
+ declare function isUnsupportedTranscriptionError(error: unknown): boolean;
76
+ declare function transcriptionRetryAfterSeconds(error: unknown): number | undefined;
77
+ /** Mime de áudio? Só áudio é transcrito — vídeo, imagem e documento passam sem tocar no engine. */
78
+ declare function isAudioMimeType(mimeType: string | undefined | null): boolean;
79
+
8
80
  declare const metaWhatsAppSchema: drizzle_orm_pg_core.PgSchema<"meta_whatsapp">;
9
81
  declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
10
82
  name: "sessions";
11
83
  schema: "meta_whatsapp";
12
84
  columns: {
13
- id: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgUUIDBuilder>>, {
14
- name: string;
85
+ id: drizzle_orm_pg_core.PgColumn<{
86
+ name: "id";
15
87
  tableName: "sessions";
16
- dataType: "string uuid";
88
+ dataType: "string";
89
+ columnType: "PgUUID";
17
90
  data: string;
18
91
  driverParam: string;
19
92
  notNull: true;
20
93
  hasDefault: true;
21
- isPrimaryKey: false;
94
+ isPrimaryKey: true;
22
95
  isAutoincrement: false;
23
96
  hasRuntimeDefault: false;
24
97
  enumValues: undefined;
98
+ baseColumn: never;
25
99
  identity: undefined;
26
100
  generated: undefined;
27
- }>;
28
- companyId: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgUUIDBuilder>, {
29
- name: string;
101
+ }, {}, {}>;
102
+ companyId: drizzle_orm_pg_core.PgColumn<{
103
+ name: "company_id";
30
104
  tableName: "sessions";
31
- dataType: "string uuid";
105
+ dataType: "string";
106
+ columnType: "PgUUID";
32
107
  data: string;
33
108
  driverParam: string;
34
109
  notNull: true;
@@ -37,13 +112,15 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
37
112
  isAutoincrement: false;
38
113
  hasRuntimeDefault: false;
39
114
  enumValues: undefined;
115
+ baseColumn: never;
40
116
  identity: undefined;
41
117
  generated: undefined;
42
- }>;
43
- whatsappNumber: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>, {
44
- name: string;
118
+ }, {}, {}>;
119
+ whatsappNumber: drizzle_orm_pg_core.PgColumn<{
120
+ name: "whatsapp_number";
45
121
  tableName: "sessions";
46
122
  dataType: "string";
123
+ columnType: "PgVarchar";
47
124
  data: string;
48
125
  driverParam: string;
49
126
  notNull: true;
@@ -51,14 +128,18 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
51
128
  isPrimaryKey: false;
52
129
  isAutoincrement: false;
53
130
  hasRuntimeDefault: false;
54
- enumValues: undefined;
131
+ enumValues: [string, ...string[]];
132
+ baseColumn: never;
55
133
  identity: undefined;
56
134
  generated: undefined;
135
+ }, {}, {
136
+ length: 20;
57
137
  }>;
58
- currentState: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>>, {
59
- name: string;
138
+ currentState: drizzle_orm_pg_core.PgColumn<{
139
+ name: "current_state";
60
140
  tableName: "sessions";
61
141
  dataType: "string";
142
+ columnType: "PgVarchar";
62
143
  data: string;
63
144
  driverParam: string;
64
145
  notNull: true;
@@ -66,14 +147,18 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
66
147
  isPrimaryKey: false;
67
148
  isAutoincrement: false;
68
149
  hasRuntimeDefault: false;
69
- enumValues: undefined;
150
+ enumValues: [string, ...string[]];
151
+ baseColumn: never;
70
152
  identity: undefined;
71
153
  generated: undefined;
154
+ }, {}, {
155
+ length: 64;
72
156
  }>;
73
- flowKey: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>, {
74
- name: string;
157
+ flowKey: drizzle_orm_pg_core.PgColumn<{
158
+ name: "flow_key";
75
159
  tableName: "sessions";
76
160
  dataType: "string";
161
+ columnType: "PgVarchar";
77
162
  data: string;
78
163
  driverParam: string;
79
164
  notNull: false;
@@ -81,14 +166,18 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
81
166
  isPrimaryKey: false;
82
167
  isAutoincrement: false;
83
168
  hasRuntimeDefault: false;
84
- enumValues: undefined;
169
+ enumValues: [string, ...string[]];
170
+ baseColumn: never;
85
171
  identity: undefined;
86
172
  generated: undefined;
173
+ }, {}, {
174
+ length: 64;
87
175
  }>;
88
- currentNodeId: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>, {
89
- name: string;
176
+ currentNodeId: drizzle_orm_pg_core.PgColumn<{
177
+ name: "current_node_id";
90
178
  tableName: "sessions";
91
179
  dataType: "string";
180
+ columnType: "PgVarchar";
92
181
  data: string;
93
182
  driverParam: string;
94
183
  notNull: false;
@@ -96,14 +185,18 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
96
185
  isPrimaryKey: false;
97
186
  isAutoincrement: false;
98
187
  hasRuntimeDefault: false;
99
- enumValues: undefined;
188
+ enumValues: [string, ...string[]];
189
+ baseColumn: never;
100
190
  identity: undefined;
101
191
  generated: undefined;
192
+ }, {}, {
193
+ length: 64;
102
194
  }>;
103
- context: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.Set$Type<drizzle_orm_pg_core.PgJsonbBuilder, Record<string, unknown>>>>, {
104
- name: string;
195
+ context: drizzle_orm_pg_core.PgColumn<{
196
+ name: "context";
105
197
  tableName: "sessions";
106
- dataType: "object json";
198
+ dataType: "json";
199
+ columnType: "PgJsonb";
107
200
  data: Record<string, unknown>;
108
201
  driverParam: unknown;
109
202
  notNull: true;
@@ -112,13 +205,17 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
112
205
  isAutoincrement: false;
113
206
  hasRuntimeDefault: false;
114
207
  enumValues: undefined;
208
+ baseColumn: never;
115
209
  identity: undefined;
116
210
  generated: undefined;
211
+ }, {}, {
212
+ $type: Record<string, unknown>;
117
213
  }>;
118
- mode: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>>, {
119
- name: string;
214
+ mode: drizzle_orm_pg_core.PgColumn<{
215
+ name: "mode";
120
216
  tableName: "sessions";
121
217
  dataType: "string";
218
+ columnType: "PgVarchar";
122
219
  data: string;
123
220
  driverParam: string;
124
221
  notNull: true;
@@ -126,14 +223,18 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
126
223
  isPrimaryKey: false;
127
224
  isAutoincrement: false;
128
225
  hasRuntimeDefault: false;
129
- enumValues: undefined;
226
+ enumValues: [string, ...string[]];
227
+ baseColumn: never;
130
228
  identity: undefined;
131
229
  generated: undefined;
230
+ }, {}, {
231
+ length: 12;
132
232
  }>;
133
- assignedUserId: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.PgUUIDBuilder, {
134
- name: string;
233
+ assignedUserId: drizzle_orm_pg_core.PgColumn<{
234
+ name: "assigned_user_id";
135
235
  tableName: "sessions";
136
- dataType: "string uuid";
236
+ dataType: "string";
237
+ columnType: "PgUUID";
137
238
  data: string;
138
239
  driverParam: string;
139
240
  notNull: false;
@@ -142,13 +243,15 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
142
243
  isAutoincrement: false;
143
244
  hasRuntimeDefault: false;
144
245
  enumValues: undefined;
246
+ baseColumn: never;
145
247
  identity: undefined;
146
248
  generated: undefined;
147
- }>;
148
- humanRequestedAt: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.PgTimestampBuilder, {
149
- name: string;
249
+ }, {}, {}>;
250
+ humanRequestedAt: drizzle_orm_pg_core.PgColumn<{
251
+ name: "human_requested_at";
150
252
  tableName: "sessions";
151
- dataType: "object date";
253
+ dataType: "date";
254
+ columnType: "PgTimestamp";
152
255
  data: Date;
153
256
  driverParam: string;
154
257
  notNull: false;
@@ -157,13 +260,15 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
157
260
  isAutoincrement: false;
158
261
  hasRuntimeDefault: false;
159
262
  enumValues: undefined;
263
+ baseColumn: never;
160
264
  identity: undefined;
161
265
  generated: undefined;
162
- }>;
163
- lastInboundAt: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.PgTimestampBuilder, {
164
- name: string;
266
+ }, {}, {}>;
267
+ lastInboundAt: drizzle_orm_pg_core.PgColumn<{
268
+ name: "last_inbound_at";
165
269
  tableName: "sessions";
166
- dataType: "object date";
270
+ dataType: "date";
271
+ columnType: "PgTimestamp";
167
272
  data: Date;
168
273
  driverParam: string;
169
274
  notNull: false;
@@ -172,13 +277,15 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
172
277
  isAutoincrement: false;
173
278
  hasRuntimeDefault: false;
174
279
  enumValues: undefined;
280
+ baseColumn: never;
175
281
  identity: undefined;
176
282
  generated: undefined;
177
- }>;
178
- lastAgentReadAt: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.PgTimestampBuilder, {
179
- name: string;
283
+ }, {}, {}>;
284
+ lastAgentReadAt: drizzle_orm_pg_core.PgColumn<{
285
+ name: "last_agent_read_at";
180
286
  tableName: "sessions";
181
- dataType: "object date";
287
+ dataType: "date";
288
+ columnType: "PgTimestamp";
182
289
  data: Date;
183
290
  driverParam: string;
184
291
  notNull: false;
@@ -187,13 +294,15 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
187
294
  isAutoincrement: false;
188
295
  hasRuntimeDefault: false;
189
296
  enumValues: undefined;
297
+ baseColumn: never;
190
298
  identity: undefined;
191
299
  generated: undefined;
192
- }>;
193
- lastActivity: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
194
- name: string;
300
+ }, {}, {}>;
301
+ lastActivity: drizzle_orm_pg_core.PgColumn<{
302
+ name: "last_activity";
195
303
  tableName: "sessions";
196
- dataType: "object date";
304
+ dataType: "date";
305
+ columnType: "PgTimestamp";
197
306
  data: Date;
198
307
  driverParam: string;
199
308
  notNull: true;
@@ -202,13 +311,15 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
202
311
  isAutoincrement: false;
203
312
  hasRuntimeDefault: false;
204
313
  enumValues: undefined;
314
+ baseColumn: never;
205
315
  identity: undefined;
206
316
  generated: undefined;
207
- }>;
208
- createdAt: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
209
- name: string;
317
+ }, {}, {}>;
318
+ createdAt: drizzle_orm_pg_core.PgColumn<{
319
+ name: "created_at";
210
320
  tableName: "sessions";
211
- dataType: "object date";
321
+ dataType: "date";
322
+ columnType: "PgTimestamp";
212
323
  data: Date;
213
324
  driverParam: string;
214
325
  notNull: true;
@@ -217,13 +328,15 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
217
328
  isAutoincrement: false;
218
329
  hasRuntimeDefault: false;
219
330
  enumValues: undefined;
331
+ baseColumn: never;
220
332
  identity: undefined;
221
333
  generated: undefined;
222
- }>;
223
- updatedAt: drizzle_orm_pg_core.PgBuildColumn<"sessions", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
224
- name: string;
334
+ }, {}, {}>;
335
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
336
+ name: "updated_at";
225
337
  tableName: "sessions";
226
- dataType: "object date";
338
+ dataType: "date";
339
+ columnType: "PgTimestamp";
227
340
  data: Date;
228
341
  driverParam: string;
229
342
  notNull: true;
@@ -232,9 +345,10 @@ declare const sessions: drizzle_orm_pg_core.PgTableWithColumns<{
232
345
  isAutoincrement: false;
233
346
  hasRuntimeDefault: false;
234
347
  enumValues: undefined;
348
+ baseColumn: never;
235
349
  identity: undefined;
236
350
  generated: undefined;
237
- }>;
351
+ }, {}, {}>;
238
352
  };
239
353
  dialect: "pg";
240
354
  }>;
@@ -242,25 +356,28 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
242
356
  name: "messages";
243
357
  schema: "meta_whatsapp";
244
358
  columns: {
245
- id: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgUUIDBuilder>>, {
246
- name: string;
359
+ id: drizzle_orm_pg_core.PgColumn<{
360
+ name: "id";
247
361
  tableName: "messages";
248
- dataType: "string uuid";
362
+ dataType: "string";
363
+ columnType: "PgUUID";
249
364
  data: string;
250
365
  driverParam: string;
251
366
  notNull: true;
252
367
  hasDefault: true;
253
- isPrimaryKey: false;
368
+ isPrimaryKey: true;
254
369
  isAutoincrement: false;
255
370
  hasRuntimeDefault: false;
256
371
  enumValues: undefined;
372
+ baseColumn: never;
257
373
  identity: undefined;
258
374
  generated: undefined;
259
- }>;
260
- companyId: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgUUIDBuilder>, {
261
- name: string;
375
+ }, {}, {}>;
376
+ companyId: drizzle_orm_pg_core.PgColumn<{
377
+ name: "company_id";
262
378
  tableName: "messages";
263
- dataType: "string uuid";
379
+ dataType: "string";
380
+ columnType: "PgUUID";
264
381
  data: string;
265
382
  driverParam: string;
266
383
  notNull: true;
@@ -269,13 +386,15 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
269
386
  isAutoincrement: false;
270
387
  hasRuntimeDefault: false;
271
388
  enumValues: undefined;
389
+ baseColumn: never;
272
390
  identity: undefined;
273
391
  generated: undefined;
274
- }>;
275
- sessionId: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgUUIDBuilder>, {
276
- name: string;
392
+ }, {}, {}>;
393
+ sessionId: drizzle_orm_pg_core.PgColumn<{
394
+ name: "session_id";
277
395
  tableName: "messages";
278
- dataType: "string uuid";
396
+ dataType: "string";
397
+ columnType: "PgUUID";
279
398
  data: string;
280
399
  driverParam: string;
281
400
  notNull: true;
@@ -284,13 +403,15 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
284
403
  isAutoincrement: false;
285
404
  hasRuntimeDefault: false;
286
405
  enumValues: undefined;
406
+ baseColumn: never;
287
407
  identity: undefined;
288
408
  generated: undefined;
289
- }>;
290
- whatsappNumber: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>, {
291
- name: string;
409
+ }, {}, {}>;
410
+ whatsappNumber: drizzle_orm_pg_core.PgColumn<{
411
+ name: "whatsapp_number";
292
412
  tableName: "messages";
293
413
  dataType: "string";
414
+ columnType: "PgVarchar";
294
415
  data: string;
295
416
  driverParam: string;
296
417
  notNull: true;
@@ -298,14 +419,18 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
298
419
  isPrimaryKey: false;
299
420
  isAutoincrement: false;
300
421
  hasRuntimeDefault: false;
301
- enumValues: undefined;
422
+ enumValues: [string, ...string[]];
423
+ baseColumn: never;
302
424
  identity: undefined;
303
425
  generated: undefined;
426
+ }, {}, {
427
+ length: 20;
304
428
  }>;
305
- direction: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>, {
306
- name: string;
429
+ direction: drizzle_orm_pg_core.PgColumn<{
430
+ name: "direction";
307
431
  tableName: "messages";
308
432
  dataType: "string";
433
+ columnType: "PgVarchar";
309
434
  data: string;
310
435
  driverParam: string;
311
436
  notNull: true;
@@ -313,14 +438,18 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
313
438
  isPrimaryKey: false;
314
439
  isAutoincrement: false;
315
440
  hasRuntimeDefault: false;
316
- enumValues: undefined;
441
+ enumValues: [string, ...string[]];
442
+ baseColumn: never;
317
443
  identity: undefined;
318
444
  generated: undefined;
445
+ }, {}, {
446
+ length: 12;
319
447
  }>;
320
- sender: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>, {
321
- name: string;
448
+ sender: drizzle_orm_pg_core.PgColumn<{
449
+ name: "sender";
322
450
  tableName: "messages";
323
451
  dataType: "string";
452
+ columnType: "PgVarchar";
324
453
  data: string;
325
454
  driverParam: string;
326
455
  notNull: true;
@@ -328,14 +457,18 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
328
457
  isPrimaryKey: false;
329
458
  isAutoincrement: false;
330
459
  hasRuntimeDefault: false;
331
- enumValues: undefined;
460
+ enumValues: [string, ...string[]];
461
+ baseColumn: never;
332
462
  identity: undefined;
333
463
  generated: undefined;
464
+ }, {}, {
465
+ length: 12;
334
466
  }>;
335
- agentUserId: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.PgUUIDBuilder, {
336
- name: string;
467
+ agentUserId: drizzle_orm_pg_core.PgColumn<{
468
+ name: "agent_user_id";
337
469
  tableName: "messages";
338
- dataType: "string uuid";
470
+ dataType: "string";
471
+ columnType: "PgUUID";
339
472
  data: string;
340
473
  driverParam: string;
341
474
  notNull: false;
@@ -344,13 +477,15 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
344
477
  isAutoincrement: false;
345
478
  hasRuntimeDefault: false;
346
479
  enumValues: undefined;
480
+ baseColumn: never;
347
481
  identity: undefined;
348
482
  generated: undefined;
349
- }>;
350
- type: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>>, {
351
- name: string;
483
+ }, {}, {}>;
484
+ type: drizzle_orm_pg_core.PgColumn<{
485
+ name: "type";
352
486
  tableName: "messages";
353
487
  dataType: "string";
488
+ columnType: "PgVarchar";
354
489
  data: string;
355
490
  driverParam: string;
356
491
  notNull: true;
@@ -358,14 +493,18 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
358
493
  isPrimaryKey: false;
359
494
  isAutoincrement: false;
360
495
  hasRuntimeDefault: false;
361
- enumValues: undefined;
496
+ enumValues: [string, ...string[]];
497
+ baseColumn: never;
362
498
  identity: undefined;
363
499
  generated: undefined;
500
+ }, {}, {
501
+ length: 32;
364
502
  }>;
365
- content: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, {
366
- name: string;
503
+ content: drizzle_orm_pg_core.PgColumn<{
504
+ name: "content";
367
505
  tableName: "messages";
368
506
  dataType: "string";
507
+ columnType: "PgText";
369
508
  data: string;
370
509
  driverParam: string;
371
510
  notNull: false;
@@ -373,14 +512,16 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
373
512
  isPrimaryKey: false;
374
513
  isAutoincrement: false;
375
514
  hasRuntimeDefault: false;
376
- enumValues: undefined;
515
+ enumValues: [string, ...string[]];
516
+ baseColumn: never;
377
517
  identity: undefined;
378
518
  generated: undefined;
379
- }>;
380
- payload: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.Set$Type<drizzle_orm_pg_core.PgJsonbBuilder, Record<string, unknown>>, {
381
- name: string;
519
+ }, {}, {}>;
520
+ payload: drizzle_orm_pg_core.PgColumn<{
521
+ name: "payload";
382
522
  tableName: "messages";
383
- dataType: "object json";
523
+ dataType: "json";
524
+ columnType: "PgJsonb";
384
525
  data: Record<string, unknown>;
385
526
  driverParam: unknown;
386
527
  notNull: false;
@@ -389,13 +530,17 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
389
530
  isAutoincrement: false;
390
531
  hasRuntimeDefault: false;
391
532
  enumValues: undefined;
533
+ baseColumn: never;
392
534
  identity: undefined;
393
535
  generated: undefined;
536
+ }, {}, {
537
+ $type: Record<string, unknown>;
394
538
  }>;
395
- waMessageId: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>, {
396
- name: string;
539
+ waMessageId: drizzle_orm_pg_core.PgColumn<{
540
+ name: "wa_message_id";
397
541
  tableName: "messages";
398
542
  dataType: "string";
543
+ columnType: "PgVarchar";
399
544
  data: string;
400
545
  driverParam: string;
401
546
  notNull: false;
@@ -403,14 +548,18 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
403
548
  isPrimaryKey: false;
404
549
  isAutoincrement: false;
405
550
  hasRuntimeDefault: false;
406
- enumValues: undefined;
551
+ enumValues: [string, ...string[]];
552
+ baseColumn: never;
407
553
  identity: undefined;
408
554
  generated: undefined;
555
+ }, {}, {
556
+ length: 128;
409
557
  }>;
410
- status: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>, {
411
- name: string;
558
+ status: drizzle_orm_pg_core.PgColumn<{
559
+ name: "status";
412
560
  tableName: "messages";
413
561
  dataType: "string";
562
+ columnType: "PgVarchar";
414
563
  data: string;
415
564
  driverParam: string;
416
565
  notNull: false;
@@ -418,14 +567,18 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
418
567
  isPrimaryKey: false;
419
568
  isAutoincrement: false;
420
569
  hasRuntimeDefault: false;
421
- enumValues: undefined;
570
+ enumValues: [string, ...string[]];
571
+ baseColumn: never;
422
572
  identity: undefined;
423
573
  generated: undefined;
574
+ }, {}, {
575
+ length: 16;
424
576
  }>;
425
- readAt: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.PgTimestampBuilder, {
426
- name: string;
577
+ readAt: drizzle_orm_pg_core.PgColumn<{
578
+ name: "read_at";
427
579
  tableName: "messages";
428
- dataType: "object date";
580
+ dataType: "date";
581
+ columnType: "PgTimestamp";
429
582
  data: Date;
430
583
  driverParam: string;
431
584
  notNull: false;
@@ -434,13 +587,126 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
434
587
  isAutoincrement: false;
435
588
  hasRuntimeDefault: false;
436
589
  enumValues: undefined;
590
+ baseColumn: never;
437
591
  identity: undefined;
438
592
  generated: undefined;
593
+ }, {}, {}>;
594
+ moderationFlagged: drizzle_orm_pg_core.PgColumn<{
595
+ name: "moderation_flagged";
596
+ tableName: "messages";
597
+ dataType: "boolean";
598
+ columnType: "PgBoolean";
599
+ data: boolean;
600
+ driverParam: boolean;
601
+ notNull: false;
602
+ hasDefault: false;
603
+ isPrimaryKey: false;
604
+ isAutoincrement: false;
605
+ hasRuntimeDefault: false;
606
+ enumValues: undefined;
607
+ baseColumn: never;
608
+ identity: undefined;
609
+ generated: undefined;
610
+ }, {}, {}>;
611
+ moderationTerms: drizzle_orm_pg_core.PgColumn<{
612
+ name: "moderation_terms";
613
+ tableName: "messages";
614
+ dataType: "json";
615
+ columnType: "PgJsonb";
616
+ data: string[];
617
+ driverParam: unknown;
618
+ notNull: false;
619
+ hasDefault: false;
620
+ isPrimaryKey: false;
621
+ isAutoincrement: false;
622
+ hasRuntimeDefault: false;
623
+ enumValues: undefined;
624
+ baseColumn: never;
625
+ identity: undefined;
626
+ generated: undefined;
627
+ }, {}, {
628
+ $type: string[];
439
629
  }>;
440
- createdAt: drizzle_orm_pg_core.PgBuildColumn<"messages", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
441
- name: string;
630
+ transcriptionStatus: drizzle_orm_pg_core.PgColumn<{
631
+ name: "transcription_status";
442
632
  tableName: "messages";
443
- dataType: "object date";
633
+ dataType: "string";
634
+ columnType: "PgVarchar";
635
+ data: TranscriptionStatus;
636
+ driverParam: string;
637
+ notNull: false;
638
+ hasDefault: false;
639
+ isPrimaryKey: false;
640
+ isAutoincrement: false;
641
+ hasRuntimeDefault: false;
642
+ enumValues: [string, ...string[]];
643
+ baseColumn: never;
644
+ identity: undefined;
645
+ generated: undefined;
646
+ }, {}, {
647
+ length: 16;
648
+ $type: TranscriptionStatus;
649
+ }>;
650
+ transcriptionText: drizzle_orm_pg_core.PgColumn<{
651
+ name: "transcription_text";
652
+ tableName: "messages";
653
+ dataType: "string";
654
+ columnType: "PgText";
655
+ data: string;
656
+ driverParam: string;
657
+ notNull: false;
658
+ hasDefault: false;
659
+ isPrimaryKey: false;
660
+ isAutoincrement: false;
661
+ hasRuntimeDefault: false;
662
+ enumValues: [string, ...string[]];
663
+ baseColumn: never;
664
+ identity: undefined;
665
+ generated: undefined;
666
+ }, {}, {}>;
667
+ transcriptionLanguage: drizzle_orm_pg_core.PgColumn<{
668
+ name: "transcription_language";
669
+ tableName: "messages";
670
+ dataType: "string";
671
+ columnType: "PgVarchar";
672
+ data: string;
673
+ driverParam: string;
674
+ notNull: false;
675
+ hasDefault: false;
676
+ isPrimaryKey: false;
677
+ isAutoincrement: false;
678
+ hasRuntimeDefault: false;
679
+ enumValues: [string, ...string[]];
680
+ baseColumn: never;
681
+ identity: undefined;
682
+ generated: undefined;
683
+ }, {}, {
684
+ length: 32;
685
+ }>;
686
+ transcriptionEngine: drizzle_orm_pg_core.PgColumn<{
687
+ name: "transcription_engine";
688
+ tableName: "messages";
689
+ dataType: "string";
690
+ columnType: "PgVarchar";
691
+ data: string;
692
+ driverParam: string;
693
+ notNull: false;
694
+ hasDefault: false;
695
+ isPrimaryKey: false;
696
+ isAutoincrement: false;
697
+ hasRuntimeDefault: false;
698
+ enumValues: [string, ...string[]];
699
+ baseColumn: never;
700
+ identity: undefined;
701
+ generated: undefined;
702
+ }, {}, {
703
+ length: 32;
704
+ }>;
705
+ createdAt: drizzle_orm_pg_core.PgColumn<{
706
+ name: "created_at";
707
+ tableName: "messages";
708
+ dataType: "date";
709
+ columnType: "PgTimestamp";
444
710
  data: Date;
445
711
  driverParam: string;
446
712
  notNull: true;
@@ -449,9 +715,226 @@ declare const messages: drizzle_orm_pg_core.PgTableWithColumns<{
449
715
  isAutoincrement: false;
450
716
  hasRuntimeDefault: false;
451
717
  enumValues: undefined;
718
+ baseColumn: never;
719
+ identity: undefined;
720
+ generated: undefined;
721
+ }, {}, {}>;
722
+ };
723
+ dialect: "pg";
724
+ }>;
725
+ /**
726
+ * Biblioteca de arquivos da conversa.
727
+ *
728
+ * Tabela própria, e não derivada de `messages.payload`: o painel precisa de `source` e `linkedAt`,
729
+ * que não existem no payload; busca por nome de arquivo quer índice, não varredura de jsonb; e
730
+ * `messageId` anulável é o que permite o atendente anexar documento à conversa sem que exista uma
731
+ * mensagem correspondente.
732
+ *
733
+ * `sessionId` em cascata apaga a LINHA junto com a conversa, mas não o binário no storage — quem
734
+ * apaga objeto é passo de aplicação (listar `uploadId` → apagar no storage → apagar a sessão).
735
+ * Confiar só na FK deixaria objeto órfão sendo cobrado para sempre.
736
+ */
737
+ declare const documents: drizzle_orm_pg_core.PgTableWithColumns<{
738
+ name: "documents";
739
+ schema: "meta_whatsapp";
740
+ columns: {
741
+ id: drizzle_orm_pg_core.PgColumn<{
742
+ name: "id";
743
+ tableName: "documents";
744
+ dataType: "string";
745
+ columnType: "PgUUID";
746
+ data: string;
747
+ driverParam: string;
748
+ notNull: true;
749
+ hasDefault: true;
750
+ isPrimaryKey: true;
751
+ isAutoincrement: false;
752
+ hasRuntimeDefault: false;
753
+ enumValues: undefined;
754
+ baseColumn: never;
755
+ identity: undefined;
756
+ generated: undefined;
757
+ }, {}, {}>;
758
+ companyId: drizzle_orm_pg_core.PgColumn<{
759
+ name: "company_id";
760
+ tableName: "documents";
761
+ dataType: "string";
762
+ columnType: "PgUUID";
763
+ data: string;
764
+ driverParam: string;
765
+ notNull: true;
766
+ hasDefault: false;
767
+ isPrimaryKey: false;
768
+ isAutoincrement: false;
769
+ hasRuntimeDefault: false;
770
+ enumValues: undefined;
771
+ baseColumn: never;
772
+ identity: undefined;
773
+ generated: undefined;
774
+ }, {}, {}>;
775
+ sessionId: drizzle_orm_pg_core.PgColumn<{
776
+ name: "session_id";
777
+ tableName: "documents";
778
+ dataType: "string";
779
+ columnType: "PgUUID";
780
+ data: string;
781
+ driverParam: string;
782
+ notNull: true;
783
+ hasDefault: false;
784
+ isPrimaryKey: false;
785
+ isAutoincrement: false;
786
+ hasRuntimeDefault: false;
787
+ enumValues: undefined;
788
+ baseColumn: never;
789
+ identity: undefined;
790
+ generated: undefined;
791
+ }, {}, {}>;
792
+ messageId: drizzle_orm_pg_core.PgColumn<{
793
+ name: "message_id";
794
+ tableName: "documents";
795
+ dataType: "string";
796
+ columnType: "PgUUID";
797
+ data: string;
798
+ driverParam: string;
799
+ notNull: false;
800
+ hasDefault: false;
801
+ isPrimaryKey: false;
802
+ isAutoincrement: false;
803
+ hasRuntimeDefault: false;
804
+ enumValues: undefined;
805
+ baseColumn: never;
806
+ identity: undefined;
807
+ generated: undefined;
808
+ }, {}, {}>;
809
+ uploadId: drizzle_orm_pg_core.PgColumn<{
810
+ name: "upload_id";
811
+ tableName: "documents";
812
+ dataType: "string";
813
+ columnType: "PgVarchar";
814
+ data: string;
815
+ driverParam: string;
816
+ notNull: true;
817
+ hasDefault: false;
818
+ isPrimaryKey: false;
819
+ isAutoincrement: false;
820
+ hasRuntimeDefault: false;
821
+ enumValues: [string, ...string[]];
822
+ baseColumn: never;
823
+ identity: undefined;
824
+ generated: undefined;
825
+ }, {}, {
826
+ length: 256;
827
+ }>;
828
+ filename: drizzle_orm_pg_core.PgColumn<{
829
+ name: "filename";
830
+ tableName: "documents";
831
+ dataType: "string";
832
+ columnType: "PgVarchar";
833
+ data: string;
834
+ driverParam: string;
835
+ notNull: true;
836
+ hasDefault: false;
837
+ isPrimaryKey: false;
838
+ isAutoincrement: false;
839
+ hasRuntimeDefault: false;
840
+ enumValues: [string, ...string[]];
841
+ baseColumn: never;
842
+ identity: undefined;
843
+ generated: undefined;
844
+ }, {}, {
845
+ length: 512;
846
+ }>;
847
+ mimeType: drizzle_orm_pg_core.PgColumn<{
848
+ name: "mime_type";
849
+ tableName: "documents";
850
+ dataType: "string";
851
+ columnType: "PgVarchar";
852
+ data: string;
853
+ driverParam: string;
854
+ notNull: true;
855
+ hasDefault: false;
856
+ isPrimaryKey: false;
857
+ isAutoincrement: false;
858
+ hasRuntimeDefault: false;
859
+ enumValues: [string, ...string[]];
860
+ baseColumn: never;
861
+ identity: undefined;
862
+ generated: undefined;
863
+ }, {}, {
864
+ length: 128;
865
+ }>;
866
+ sizeBytes: drizzle_orm_pg_core.PgColumn<{
867
+ name: "size_bytes";
868
+ tableName: "documents";
869
+ dataType: "number";
870
+ columnType: "PgInteger";
871
+ data: number;
872
+ driverParam: string | number;
873
+ notNull: true;
874
+ hasDefault: false;
875
+ isPrimaryKey: false;
876
+ isAutoincrement: false;
877
+ hasRuntimeDefault: false;
878
+ enumValues: undefined;
879
+ baseColumn: never;
880
+ identity: undefined;
881
+ generated: undefined;
882
+ }, {}, {}>;
883
+ sha256: drizzle_orm_pg_core.PgColumn<{
884
+ name: "sha256";
885
+ tableName: "documents";
886
+ dataType: "string";
887
+ columnType: "PgVarchar";
888
+ data: string;
889
+ driverParam: string;
890
+ notNull: false;
891
+ hasDefault: false;
892
+ isPrimaryKey: false;
893
+ isAutoincrement: false;
894
+ hasRuntimeDefault: false;
895
+ enumValues: [string, ...string[]];
896
+ baseColumn: never;
897
+ identity: undefined;
898
+ generated: undefined;
899
+ }, {}, {
900
+ length: 64;
901
+ }>;
902
+ source: drizzle_orm_pg_core.PgColumn<{
903
+ name: "source";
904
+ tableName: "documents";
905
+ dataType: "string";
906
+ columnType: "PgVarchar";
907
+ data: string;
908
+ driverParam: string;
909
+ notNull: true;
910
+ hasDefault: false;
911
+ isPrimaryKey: false;
912
+ isAutoincrement: false;
913
+ hasRuntimeDefault: false;
914
+ enumValues: [string, ...string[]];
915
+ baseColumn: never;
452
916
  identity: undefined;
453
917
  generated: undefined;
918
+ }, {}, {
919
+ length: 12;
454
920
  }>;
921
+ linkedAt: drizzle_orm_pg_core.PgColumn<{
922
+ name: "linked_at";
923
+ tableName: "documents";
924
+ dataType: "date";
925
+ columnType: "PgTimestamp";
926
+ data: Date;
927
+ driverParam: string;
928
+ notNull: true;
929
+ hasDefault: true;
930
+ isPrimaryKey: false;
931
+ isAutoincrement: false;
932
+ hasRuntimeDefault: false;
933
+ enumValues: undefined;
934
+ baseColumn: never;
935
+ identity: undefined;
936
+ generated: undefined;
937
+ }, {}, {}>;
455
938
  };
456
939
  dialect: "pg";
457
940
  }>;
@@ -459,25 +942,64 @@ declare const flowGraphs: drizzle_orm_pg_core.PgTableWithColumns<{
459
942
  name: "flow_graphs";
460
943
  schema: "meta_whatsapp";
461
944
  columns: {
462
- id: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgUUIDBuilder>>, {
463
- name: string;
945
+ id: drizzle_orm_pg_core.PgColumn<{
946
+ name: "id";
464
947
  tableName: "flow_graphs";
465
- dataType: "string uuid";
948
+ dataType: "string";
949
+ columnType: "PgUUID";
466
950
  data: string;
467
951
  driverParam: string;
468
952
  notNull: true;
469
953
  hasDefault: true;
954
+ isPrimaryKey: true;
955
+ isAutoincrement: false;
956
+ hasRuntimeDefault: false;
957
+ enumValues: undefined;
958
+ baseColumn: never;
959
+ identity: undefined;
960
+ generated: undefined;
961
+ }, {}, {}>;
962
+ companyId: drizzle_orm_pg_core.PgColumn<{
963
+ name: "company_id";
964
+ tableName: "flow_graphs";
965
+ dataType: "string";
966
+ columnType: "PgUUID";
967
+ data: string;
968
+ driverParam: string;
969
+ notNull: true;
970
+ hasDefault: false;
470
971
  isPrimaryKey: false;
471
972
  isAutoincrement: false;
472
973
  hasRuntimeDefault: false;
473
974
  enumValues: undefined;
975
+ baseColumn: never;
474
976
  identity: undefined;
475
977
  generated: undefined;
978
+ }, {}, {}>;
979
+ key: drizzle_orm_pg_core.PgColumn<{
980
+ name: "key";
981
+ tableName: "flow_graphs";
982
+ dataType: "string";
983
+ columnType: "PgVarchar";
984
+ data: string;
985
+ driverParam: string;
986
+ notNull: true;
987
+ hasDefault: false;
988
+ isPrimaryKey: false;
989
+ isAutoincrement: false;
990
+ hasRuntimeDefault: false;
991
+ enumValues: [string, ...string[]];
992
+ baseColumn: never;
993
+ identity: undefined;
994
+ generated: undefined;
995
+ }, {}, {
996
+ length: 64;
476
997
  }>;
477
- companyId: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgUUIDBuilder>, {
478
- name: string;
998
+ label: drizzle_orm_pg_core.PgColumn<{
999
+ name: "label";
479
1000
  tableName: "flow_graphs";
480
- dataType: "string uuid";
1001
+ dataType: "string";
1002
+ columnType: "PgVarchar";
481
1003
  data: string;
482
1004
  driverParam: string;
483
1005
  notNull: true;
@@ -485,14 +1007,18 @@ declare const flowGraphs: drizzle_orm_pg_core.PgTableWithColumns<{
485
1007
  isPrimaryKey: false;
486
1008
  isAutoincrement: false;
487
1009
  hasRuntimeDefault: false;
488
- enumValues: undefined;
1010
+ enumValues: [string, ...string[]];
1011
+ baseColumn: never;
489
1012
  identity: undefined;
490
1013
  generated: undefined;
1014
+ }, {}, {
1015
+ length: 120;
491
1016
  }>;
492
- key: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>, {
493
- name: string;
1017
+ startNodeId: drizzle_orm_pg_core.PgColumn<{
1018
+ name: "start_node_id";
494
1019
  tableName: "flow_graphs";
495
1020
  dataType: "string";
1021
+ columnType: "PgVarchar";
496
1022
  data: string;
497
1023
  driverParam: string;
498
1024
  notNull: true;
@@ -500,59 +1026,307 @@ declare const flowGraphs: drizzle_orm_pg_core.PgTableWithColumns<{
500
1026
  isPrimaryKey: false;
501
1027
  isAutoincrement: false;
502
1028
  hasRuntimeDefault: false;
1029
+ enumValues: [string, ...string[]];
1030
+ baseColumn: never;
1031
+ identity: undefined;
1032
+ generated: undefined;
1033
+ }, {}, {
1034
+ length: 64;
1035
+ }>;
1036
+ nodes: drizzle_orm_pg_core.PgColumn<{
1037
+ name: "nodes";
1038
+ tableName: "flow_graphs";
1039
+ dataType: "json";
1040
+ columnType: "PgJsonb";
1041
+ data: Record<string, unknown>;
1042
+ driverParam: unknown;
1043
+ notNull: true;
1044
+ hasDefault: true;
1045
+ isPrimaryKey: false;
1046
+ isAutoincrement: false;
1047
+ hasRuntimeDefault: false;
503
1048
  enumValues: undefined;
1049
+ baseColumn: never;
504
1050
  identity: undefined;
505
1051
  generated: undefined;
1052
+ }, {}, {
1053
+ $type: Record<string, unknown>;
506
1054
  }>;
507
- label: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>, {
508
- name: string;
1055
+ version: drizzle_orm_pg_core.PgColumn<{
1056
+ name: "version";
1057
+ tableName: "flow_graphs";
1058
+ dataType: "number";
1059
+ columnType: "PgInteger";
1060
+ data: number;
1061
+ driverParam: string | number;
1062
+ notNull: true;
1063
+ hasDefault: true;
1064
+ isPrimaryKey: false;
1065
+ isAutoincrement: false;
1066
+ hasRuntimeDefault: false;
1067
+ enumValues: undefined;
1068
+ baseColumn: never;
1069
+ identity: undefined;
1070
+ generated: undefined;
1071
+ }, {}, {}>;
1072
+ showInMenu: drizzle_orm_pg_core.PgColumn<{
1073
+ name: "show_in_menu";
1074
+ tableName: "flow_graphs";
1075
+ dataType: "boolean";
1076
+ columnType: "PgBoolean";
1077
+ data: boolean;
1078
+ driverParam: boolean;
1079
+ notNull: true;
1080
+ hasDefault: true;
1081
+ isPrimaryKey: false;
1082
+ isAutoincrement: false;
1083
+ hasRuntimeDefault: false;
1084
+ enumValues: undefined;
1085
+ baseColumn: never;
1086
+ identity: undefined;
1087
+ generated: undefined;
1088
+ }, {}, {}>;
1089
+ menuOptionLabel: drizzle_orm_pg_core.PgColumn<{
1090
+ name: "menu_option_label";
509
1091
  tableName: "flow_graphs";
510
1092
  dataType: "string";
1093
+ columnType: "PgVarchar";
511
1094
  data: string;
512
1095
  driverParam: string;
1096
+ notNull: false;
1097
+ hasDefault: false;
1098
+ isPrimaryKey: false;
1099
+ isAutoincrement: false;
1100
+ hasRuntimeDefault: false;
1101
+ enumValues: [string, ...string[]];
1102
+ baseColumn: never;
1103
+ identity: undefined;
1104
+ generated: undefined;
1105
+ }, {}, {
1106
+ length: 64;
1107
+ }>;
1108
+ createdAt: drizzle_orm_pg_core.PgColumn<{
1109
+ name: "created_at";
1110
+ tableName: "flow_graphs";
1111
+ dataType: "date";
1112
+ columnType: "PgTimestamp";
1113
+ data: Date;
1114
+ driverParam: string;
1115
+ notNull: true;
1116
+ hasDefault: true;
1117
+ isPrimaryKey: false;
1118
+ isAutoincrement: false;
1119
+ hasRuntimeDefault: false;
1120
+ enumValues: undefined;
1121
+ baseColumn: never;
1122
+ identity: undefined;
1123
+ generated: undefined;
1124
+ }, {}, {}>;
1125
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
1126
+ name: "updated_at";
1127
+ tableName: "flow_graphs";
1128
+ dataType: "date";
1129
+ columnType: "PgTimestamp";
1130
+ data: Date;
1131
+ driverParam: string;
1132
+ notNull: true;
1133
+ hasDefault: true;
1134
+ isPrimaryKey: false;
1135
+ isAutoincrement: false;
1136
+ hasRuntimeDefault: false;
1137
+ enumValues: undefined;
1138
+ baseColumn: never;
1139
+ identity: undefined;
1140
+ generated: undefined;
1141
+ }, {}, {}>;
1142
+ };
1143
+ dialect: "pg";
1144
+ }>;
1145
+ /**
1146
+ * Biblioteca de mídia do bot: arquivos que um nó `action` de `send_media` dispara ao chegar nele.
1147
+ *
1148
+ * Tabela separada de `documents` de propósito, e não por simetria: `documents` é o acervo DE UMA
1149
+ * CONVERSA (tem `sessionId` obrigatório) e tem índice único em (companyId, uploadId), porque lá o
1150
+ * mesmo binário chegando duas vezes é reentrega de job. Aqui é o oposto — o mesmo arquivo é
1151
+ * enviado para todo cliente que passar pelo nó, então aquele único bloquearia o segundo envio.
1152
+ *
1153
+ * Sem FK para `flow_graphs.id`: o vínculo natural é (companyId, flowKey), que é justamente o
1154
+ * índice único de lá. `nodeId` não tem como ser FK — nós vivem dentro do jsonb `nodes` — então
1155
+ * apagar um nó no editor deixa a linha órfã; quem lista sempre parte de um nó existente, e a
1156
+ * limpeza é passo de aplicação ao salvar o grafo.
1157
+ */
1158
+ declare const flowMedia: drizzle_orm_pg_core.PgTableWithColumns<{
1159
+ name: "flow_media";
1160
+ schema: "meta_whatsapp";
1161
+ columns: {
1162
+ id: drizzle_orm_pg_core.PgColumn<{
1163
+ name: "id";
1164
+ tableName: "flow_media";
1165
+ dataType: "string";
1166
+ columnType: "PgUUID";
1167
+ data: string;
1168
+ driverParam: string;
1169
+ notNull: true;
1170
+ hasDefault: true;
1171
+ isPrimaryKey: true;
1172
+ isAutoincrement: false;
1173
+ hasRuntimeDefault: false;
1174
+ enumValues: undefined;
1175
+ baseColumn: never;
1176
+ identity: undefined;
1177
+ generated: undefined;
1178
+ }, {}, {}>;
1179
+ companyId: drizzle_orm_pg_core.PgColumn<{
1180
+ name: "company_id";
1181
+ tableName: "flow_media";
1182
+ dataType: "string";
1183
+ columnType: "PgUUID";
1184
+ data: string;
1185
+ driverParam: string;
1186
+ notNull: true;
1187
+ hasDefault: false;
1188
+ isPrimaryKey: false;
1189
+ isAutoincrement: false;
1190
+ hasRuntimeDefault: false;
1191
+ enumValues: undefined;
1192
+ baseColumn: never;
1193
+ identity: undefined;
1194
+ generated: undefined;
1195
+ }, {}, {}>;
1196
+ flowKey: drizzle_orm_pg_core.PgColumn<{
1197
+ name: "flow_key";
1198
+ tableName: "flow_media";
1199
+ dataType: "string";
1200
+ columnType: "PgVarchar";
1201
+ data: string;
1202
+ driverParam: string;
1203
+ notNull: true;
1204
+ hasDefault: false;
1205
+ isPrimaryKey: false;
1206
+ isAutoincrement: false;
1207
+ hasRuntimeDefault: false;
1208
+ enumValues: [string, ...string[]];
1209
+ baseColumn: never;
1210
+ identity: undefined;
1211
+ generated: undefined;
1212
+ }, {}, {
1213
+ length: 64;
1214
+ }>;
1215
+ nodeId: drizzle_orm_pg_core.PgColumn<{
1216
+ name: "node_id";
1217
+ tableName: "flow_media";
1218
+ dataType: "string";
1219
+ columnType: "PgVarchar";
1220
+ data: string;
1221
+ driverParam: string;
1222
+ notNull: true;
1223
+ hasDefault: false;
1224
+ isPrimaryKey: false;
1225
+ isAutoincrement: false;
1226
+ hasRuntimeDefault: false;
1227
+ enumValues: [string, ...string[]];
1228
+ baseColumn: never;
1229
+ identity: undefined;
1230
+ generated: undefined;
1231
+ }, {}, {
1232
+ length: 64;
1233
+ }>;
1234
+ uploadId: drizzle_orm_pg_core.PgColumn<{
1235
+ name: "upload_id";
1236
+ tableName: "flow_media";
1237
+ dataType: "string";
1238
+ columnType: "PgVarchar";
1239
+ data: string;
1240
+ driverParam: string;
1241
+ notNull: true;
1242
+ hasDefault: false;
1243
+ isPrimaryKey: false;
1244
+ isAutoincrement: false;
1245
+ hasRuntimeDefault: false;
1246
+ enumValues: [string, ...string[]];
1247
+ baseColumn: never;
1248
+ identity: undefined;
1249
+ generated: undefined;
1250
+ }, {}, {
1251
+ length: 256;
1252
+ }>;
1253
+ filename: drizzle_orm_pg_core.PgColumn<{
1254
+ name: "filename";
1255
+ tableName: "flow_media";
1256
+ dataType: "string";
1257
+ columnType: "PgVarchar";
1258
+ data: string;
1259
+ driverParam: string;
1260
+ notNull: true;
1261
+ hasDefault: false;
1262
+ isPrimaryKey: false;
1263
+ isAutoincrement: false;
1264
+ hasRuntimeDefault: false;
1265
+ enumValues: [string, ...string[]];
1266
+ baseColumn: never;
1267
+ identity: undefined;
1268
+ generated: undefined;
1269
+ }, {}, {
1270
+ length: 512;
1271
+ }>;
1272
+ mimeType: drizzle_orm_pg_core.PgColumn<{
1273
+ name: "mime_type";
1274
+ tableName: "flow_media";
1275
+ dataType: "string";
1276
+ columnType: "PgVarchar";
1277
+ data: string;
1278
+ driverParam: string;
1279
+ notNull: true;
1280
+ hasDefault: false;
1281
+ isPrimaryKey: false;
1282
+ isAutoincrement: false;
1283
+ hasRuntimeDefault: false;
1284
+ enumValues: [string, ...string[]];
1285
+ baseColumn: never;
1286
+ identity: undefined;
1287
+ generated: undefined;
1288
+ }, {}, {
1289
+ length: 128;
1290
+ }>;
1291
+ sizeBytes: drizzle_orm_pg_core.PgColumn<{
1292
+ name: "size_bytes";
1293
+ tableName: "flow_media";
1294
+ dataType: "number";
1295
+ columnType: "PgInteger";
1296
+ data: number;
1297
+ driverParam: string | number;
513
1298
  notNull: true;
514
1299
  hasDefault: false;
515
1300
  isPrimaryKey: false;
516
1301
  isAutoincrement: false;
517
1302
  hasRuntimeDefault: false;
518
1303
  enumValues: undefined;
1304
+ baseColumn: never;
519
1305
  identity: undefined;
520
1306
  generated: undefined;
521
- }>;
522
- startNodeId: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>, {
523
- name: string;
524
- tableName: "flow_graphs";
1307
+ }, {}, {}>;
1308
+ caption: drizzle_orm_pg_core.PgColumn<{
1309
+ name: "caption";
1310
+ tableName: "flow_media";
525
1311
  dataType: "string";
1312
+ columnType: "PgText";
526
1313
  data: string;
527
1314
  driverParam: string;
528
- notNull: true;
1315
+ notNull: false;
529
1316
  hasDefault: false;
530
1317
  isPrimaryKey: false;
531
1318
  isAutoincrement: false;
532
1319
  hasRuntimeDefault: false;
533
- enumValues: undefined;
534
- identity: undefined;
535
- generated: undefined;
536
- }>;
537
- nodes: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.Set$Type<drizzle_orm_pg_core.PgJsonbBuilder, Record<string, unknown>>>>, {
538
- name: string;
539
- tableName: "flow_graphs";
540
- dataType: "object json";
541
- data: Record<string, unknown>;
542
- driverParam: unknown;
543
- notNull: true;
544
- hasDefault: true;
545
- isPrimaryKey: false;
546
- isAutoincrement: false;
547
- hasRuntimeDefault: false;
548
- enumValues: undefined;
1320
+ enumValues: [string, ...string[]];
1321
+ baseColumn: never;
549
1322
  identity: undefined;
550
1323
  generated: undefined;
551
- }>;
552
- version: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgIntegerBuilder>>, {
553
- name: string;
554
- tableName: "flow_graphs";
555
- dataType: "number int32";
1324
+ }, {}, {}>;
1325
+ sortOrder: drizzle_orm_pg_core.PgColumn<{
1326
+ name: "sort_order";
1327
+ tableName: "flow_media";
1328
+ dataType: "number";
1329
+ columnType: "PgInteger";
556
1330
  data: number;
557
1331
  driverParam: string | number;
558
1332
  notNull: true;
@@ -561,13 +1335,15 @@ declare const flowGraphs: drizzle_orm_pg_core.PgTableWithColumns<{
561
1335
  isAutoincrement: false;
562
1336
  hasRuntimeDefault: false;
563
1337
  enumValues: undefined;
1338
+ baseColumn: never;
564
1339
  identity: undefined;
565
1340
  generated: undefined;
566
- }>;
567
- showInMenu: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBooleanBuilder>>, {
568
- name: string;
569
- tableName: "flow_graphs";
1341
+ }, {}, {}>;
1342
+ active: drizzle_orm_pg_core.PgColumn<{
1343
+ name: "active";
1344
+ tableName: "flow_media";
570
1345
  dataType: "boolean";
1346
+ columnType: "PgBoolean";
571
1347
  data: boolean;
572
1348
  driverParam: boolean;
573
1349
  notNull: true;
@@ -576,28 +1352,15 @@ declare const flowGraphs: drizzle_orm_pg_core.PgTableWithColumns<{
576
1352
  isAutoincrement: false;
577
1353
  hasRuntimeDefault: false;
578
1354
  enumValues: undefined;
1355
+ baseColumn: never;
579
1356
  identity: undefined;
580
1357
  generated: undefined;
581
- }>;
582
- menuOptionLabel: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>, {
583
- name: string;
584
- tableName: "flow_graphs";
585
- dataType: "string";
586
- data: string;
587
- driverParam: string;
588
- notNull: false;
589
- hasDefault: false;
590
- isPrimaryKey: false;
591
- isAutoincrement: false;
592
- hasRuntimeDefault: false;
593
- enumValues: undefined;
594
- identity: undefined;
595
- generated: undefined;
596
- }>;
597
- createdAt: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
598
- name: string;
599
- tableName: "flow_graphs";
600
- dataType: "object date";
1358
+ }, {}, {}>;
1359
+ createdAt: drizzle_orm_pg_core.PgColumn<{
1360
+ name: "created_at";
1361
+ tableName: "flow_media";
1362
+ dataType: "date";
1363
+ columnType: "PgTimestamp";
601
1364
  data: Date;
602
1365
  driverParam: string;
603
1366
  notNull: true;
@@ -606,13 +1369,15 @@ declare const flowGraphs: drizzle_orm_pg_core.PgTableWithColumns<{
606
1369
  isAutoincrement: false;
607
1370
  hasRuntimeDefault: false;
608
1371
  enumValues: undefined;
1372
+ baseColumn: never;
609
1373
  identity: undefined;
610
1374
  generated: undefined;
611
- }>;
612
- updatedAt: drizzle_orm_pg_core.PgBuildColumn<"flow_graphs", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
613
- name: string;
614
- tableName: "flow_graphs";
615
- dataType: "object date";
1375
+ }, {}, {}>;
1376
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
1377
+ name: "updated_at";
1378
+ tableName: "flow_media";
1379
+ dataType: "date";
1380
+ columnType: "PgTimestamp";
616
1381
  data: Date;
617
1382
  driverParam: string;
618
1383
  notNull: true;
@@ -621,9 +1386,10 @@ declare const flowGraphs: drizzle_orm_pg_core.PgTableWithColumns<{
621
1386
  isAutoincrement: false;
622
1387
  hasRuntimeDefault: false;
623
1388
  enumValues: undefined;
1389
+ baseColumn: never;
624
1390
  identity: undefined;
625
1391
  generated: undefined;
626
- }>;
1392
+ }, {}, {}>;
627
1393
  };
628
1394
  dialect: "pg";
629
1395
  }>;
@@ -631,25 +1397,28 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
631
1397
  name: "settings";
632
1398
  schema: "meta_whatsapp";
633
1399
  columns: {
634
- companyId: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgUUIDBuilder>, {
635
- name: string;
1400
+ companyId: drizzle_orm_pg_core.PgColumn<{
1401
+ name: "company_id";
636
1402
  tableName: "settings";
637
- dataType: "string uuid";
1403
+ dataType: "string";
1404
+ columnType: "PgUUID";
638
1405
  data: string;
639
1406
  driverParam: string;
640
1407
  notNull: true;
641
1408
  hasDefault: false;
642
- isPrimaryKey: false;
1409
+ isPrimaryKey: true;
643
1410
  isAutoincrement: false;
644
1411
  hasRuntimeDefault: false;
645
1412
  enumValues: undefined;
1413
+ baseColumn: never;
646
1414
  identity: undefined;
647
1415
  generated: undefined;
648
- }>;
649
- templateName: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>, {
650
- name: string;
1416
+ }, {}, {}>;
1417
+ templateName: drizzle_orm_pg_core.PgColumn<{
1418
+ name: "template_name";
651
1419
  tableName: "settings";
652
1420
  dataType: "string";
1421
+ columnType: "PgVarchar";
653
1422
  data: string;
654
1423
  driverParam: string;
655
1424
  notNull: false;
@@ -657,14 +1426,18 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
657
1426
  isPrimaryKey: false;
658
1427
  isAutoincrement: false;
659
1428
  hasRuntimeDefault: false;
660
- enumValues: undefined;
1429
+ enumValues: [string, ...string[]];
1430
+ baseColumn: never;
661
1431
  identity: undefined;
662
1432
  generated: undefined;
1433
+ }, {}, {
1434
+ length: 128;
663
1435
  }>;
664
- templateLanguage: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgVarcharBuilder<[string, ...string[]]>>>, {
665
- name: string;
1436
+ templateLanguage: drizzle_orm_pg_core.PgColumn<{
1437
+ name: "template_language";
666
1438
  tableName: "settings";
667
1439
  dataType: "string";
1440
+ columnType: "PgVarchar";
668
1441
  data: string;
669
1442
  driverParam: string;
670
1443
  notNull: true;
@@ -672,14 +1445,18 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
672
1445
  isPrimaryKey: false;
673
1446
  isAutoincrement: false;
674
1447
  hasRuntimeDefault: false;
675
- enumValues: undefined;
1448
+ enumValues: [string, ...string[]];
1449
+ baseColumn: never;
676
1450
  identity: undefined;
677
1451
  generated: undefined;
1452
+ }, {}, {
1453
+ length: 16;
678
1454
  }>;
679
- templateVariables: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.Set$Type<drizzle_orm_pg_core.PgJsonbBuilder, string[]>>>, {
680
- name: string;
1455
+ templateVariables: drizzle_orm_pg_core.PgColumn<{
1456
+ name: "template_variables";
681
1457
  tableName: "settings";
682
- dataType: "object json";
1458
+ dataType: "json";
1459
+ columnType: "PgJsonb";
683
1460
  data: string[];
684
1461
  driverParam: unknown;
685
1462
  notNull: true;
@@ -688,13 +1465,17 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
688
1465
  isAutoincrement: false;
689
1466
  hasRuntimeDefault: false;
690
1467
  enumValues: undefined;
1468
+ baseColumn: never;
691
1469
  identity: undefined;
692
1470
  generated: undefined;
1471
+ }, {}, {
1472
+ $type: string[];
693
1473
  }>;
694
- welcomeMessage: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, {
695
- name: string;
1474
+ welcomeMessage: drizzle_orm_pg_core.PgColumn<{
1475
+ name: "welcome_message";
696
1476
  tableName: "settings";
697
1477
  dataType: "string";
1478
+ columnType: "PgText";
698
1479
  data: string;
699
1480
  driverParam: string;
700
1481
  notNull: false;
@@ -702,14 +1483,16 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
702
1483
  isPrimaryKey: false;
703
1484
  isAutoincrement: false;
704
1485
  hasRuntimeDefault: false;
705
- enumValues: undefined;
1486
+ enumValues: [string, ...string[]];
1487
+ baseColumn: never;
706
1488
  identity: undefined;
707
1489
  generated: undefined;
708
- }>;
709
- farewellMessage: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, {
710
- name: string;
1490
+ }, {}, {}>;
1491
+ farewellMessage: drizzle_orm_pg_core.PgColumn<{
1492
+ name: "farewell_message";
711
1493
  tableName: "settings";
712
1494
  dataType: "string";
1495
+ columnType: "PgText";
713
1496
  data: string;
714
1497
  driverParam: string;
715
1498
  notNull: false;
@@ -717,14 +1500,53 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
717
1500
  isPrimaryKey: false;
718
1501
  isAutoincrement: false;
719
1502
  hasRuntimeDefault: false;
1503
+ enumValues: [string, ...string[]];
1504
+ baseColumn: never;
1505
+ identity: undefined;
1506
+ generated: undefined;
1507
+ }, {}, {}>;
1508
+ transcriptionEnabled: drizzle_orm_pg_core.PgColumn<{
1509
+ name: "transcription_enabled";
1510
+ tableName: "settings";
1511
+ dataType: "boolean";
1512
+ columnType: "PgBoolean";
1513
+ data: boolean;
1514
+ driverParam: boolean;
1515
+ notNull: false;
1516
+ hasDefault: false;
1517
+ isPrimaryKey: false;
1518
+ isAutoincrement: false;
1519
+ hasRuntimeDefault: false;
720
1520
  enumValues: undefined;
1521
+ baseColumn: never;
1522
+ identity: undefined;
1523
+ generated: undefined;
1524
+ }, {}, {}>;
1525
+ transcriptionMode: drizzle_orm_pg_core.PgColumn<{
1526
+ name: "transcription_mode";
1527
+ tableName: "settings";
1528
+ dataType: "string";
1529
+ columnType: "PgVarchar";
1530
+ data: TranscriptionMode;
1531
+ driverParam: string;
1532
+ notNull: false;
1533
+ hasDefault: false;
1534
+ isPrimaryKey: false;
1535
+ isAutoincrement: false;
1536
+ hasRuntimeDefault: false;
1537
+ enumValues: [string, ...string[]];
1538
+ baseColumn: never;
721
1539
  identity: undefined;
722
1540
  generated: undefined;
1541
+ }, {}, {
1542
+ length: 16;
1543
+ $type: TranscriptionMode;
723
1544
  }>;
724
- createdAt: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
725
- name: string;
1545
+ createdAt: drizzle_orm_pg_core.PgColumn<{
1546
+ name: "created_at";
726
1547
  tableName: "settings";
727
- dataType: "object date";
1548
+ dataType: "date";
1549
+ columnType: "PgTimestamp";
728
1550
  data: Date;
729
1551
  driverParam: string;
730
1552
  notNull: true;
@@ -733,13 +1555,15 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
733
1555
  isAutoincrement: false;
734
1556
  hasRuntimeDefault: false;
735
1557
  enumValues: undefined;
1558
+ baseColumn: never;
736
1559
  identity: undefined;
737
1560
  generated: undefined;
738
- }>;
739
- updatedAt: drizzle_orm_pg_core.PgBuildColumn<"settings", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
740
- name: string;
1561
+ }, {}, {}>;
1562
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
1563
+ name: "updated_at";
741
1564
  tableName: "settings";
742
- dataType: "object date";
1565
+ dataType: "date";
1566
+ columnType: "PgTimestamp";
743
1567
  data: Date;
744
1568
  driverParam: string;
745
1569
  notNull: true;
@@ -748,9 +1572,10 @@ declare const settings: drizzle_orm_pg_core.PgTableWithColumns<{
748
1572
  isAutoincrement: false;
749
1573
  hasRuntimeDefault: false;
750
1574
  enumValues: undefined;
1575
+ baseColumn: never;
751
1576
  identity: undefined;
752
1577
  generated: undefined;
753
- }>;
1578
+ }, {}, {}>;
754
1579
  };
755
1580
  dialect: "pg";
756
1581
  }>;
@@ -762,6 +1587,10 @@ type MessageRow = typeof messages.$inferSelect;
762
1587
  type NewMessageRow = typeof messages.$inferInsert;
763
1588
  type FlowGraphRow = typeof flowGraphs.$inferSelect;
764
1589
  type NewFlowGraphRow = typeof flowGraphs.$inferInsert;
1590
+ type DocumentRow = typeof documents.$inferSelect;
1591
+ type NewDocumentRow = typeof documents.$inferInsert;
1592
+ type FlowMediaRow = typeof flowMedia.$inferSelect;
1593
+ type NewFlowMediaRow = typeof flowMedia.$inferInsert;
765
1594
 
766
1595
  interface ListConversationsFilters {
767
1596
  page?: number;
@@ -771,16 +1600,26 @@ interface ListConversationsFilters {
771
1600
  }
772
1601
  declare class SessionRepository {
773
1602
  private readonly db;
774
- constructor(db: BunSQLDatabase<AnyRelations | EmptyRelations>);
1603
+ constructor(db: MetaWhatsAppDatabase);
775
1604
  getContext(companyId: string, whatsappNumber: string): Promise<SessionRow | undefined>;
776
1605
  getOrCreate(companyId: string, whatsappNumber: string, startState: SessionState): Promise<SessionRow>;
777
- setState(companyId: string, whatsappNumber: string, state: SessionState, context?: Record<string, unknown>): Promise<void>;
1606
+ setState<TSessionContext extends Record<string, unknown> = Record<string, unknown>>(companyId: string, whatsappNumber: string, state: SessionState, context?: TSessionContext): Promise<void>;
1607
+ patchContext<TSessionContext extends Record<string, unknown> = Record<string, unknown>>(companyId: string, whatsappNumber: string, patch: Partial<TSessionContext>): Promise<void>;
1608
+ readContext<TSessionContext extends Record<string, unknown> = Record<string, unknown>>(companyId: string, whatsappNumber: string): Promise<TSessionContext | undefined>;
778
1609
  setFlowPosition(companyId: string, whatsappNumber: string, flowKey: string | null, currentNodeId: string | null): Promise<void>;
779
1610
  touchInbound(companyId: string, whatsappNumber: string): Promise<void>;
780
1611
  hoursSinceLastInbound(companyId: string, whatsappNumber: string): Promise<number | undefined>;
781
1612
  setMode(companyId: string, whatsappNumber: string, mode: SessionMode, assignedUserId?: string | null): Promise<void>;
782
1613
  takeover(companyId: string, whatsappNumber: string, agentUserId: string): Promise<void>;
783
1614
  release(companyId: string, whatsappNumber: string): Promise<void>;
1615
+ /**
1616
+ * Apaga a sessão; a cascata das FKs leva mensagens e documentos.
1617
+ *
1618
+ * Não apaga o binário no storage — isso é passo de aplicação, e é por isso que este método é
1619
+ * chamado por `DeleteConversationUseCase` e não diretamente pelo host. Chamar daqui sem apagar os
1620
+ * objetos antes deixa mídia órfã sendo cobrada para sempre.
1621
+ */
1622
+ deleteByNumber(companyId: string, whatsappNumber: string): Promise<void>;
784
1623
  requestHuman(companyId: string, whatsappNumber: string): Promise<void>;
785
1624
  markRead(companyId: string, whatsappNumber: string): Promise<void>;
786
1625
  markAllRead(companyId: string, userId: string): Promise<number>;
@@ -817,11 +1656,108 @@ declare class SessionRepository {
817
1656
  waMessageId: string | null;
818
1657
  status: string | null;
819
1658
  readAt: Date | null;
1659
+ moderationFlagged: boolean | null;
1660
+ moderationTerms: string[] | null;
1661
+ transcriptionStatus: TranscriptionStatus | null;
1662
+ transcriptionText: string | null;
1663
+ transcriptionLanguage: string | null;
1664
+ transcriptionEngine: string | null;
820
1665
  createdAt: Date;
821
1666
  }[];
822
1667
  } | null>;
823
1668
  }
824
1669
 
1670
+ interface InsertMessageParams {
1671
+ companyId: string;
1672
+ sessionId: string;
1673
+ whatsappNumber: string;
1674
+ direction: MessageDirection;
1675
+ sender: MessageSender;
1676
+ agentUserId?: string | null;
1677
+ type: string;
1678
+ content?: string | null;
1679
+ payload?: Record<string, unknown> | null;
1680
+ waMessageId?: string | null;
1681
+ status?: MessageStatus | null;
1682
+ /** `undefined` deixa a coluna nula: não avaliado, distinto de avaliado e limpo. */
1683
+ moderationFlagged?: boolean | null;
1684
+ moderationTerms?: string[] | null;
1685
+ }
1686
+ interface ListMessagesParams$1 {
1687
+ companyId: string;
1688
+ sessionId: string;
1689
+ limit?: number;
1690
+ before?: string;
1691
+ }
1692
+ interface SaveTranscriptionByWaMessageIdParams extends Omit<SaveTranscriptionParams, 'messageId'> {
1693
+ /**
1694
+ * Id da mensagem na Meta. É o único que quem processa o webhook conhece — o id do módulo só
1695
+ * existe depois da gravação, e obrigar o host a descobri-lo faria cada um escrever a própria
1696
+ * consulta por `wa_message_id`.
1697
+ */
1698
+ waMessageId: string;
1699
+ }
1700
+ interface SaveTranscriptionParams {
1701
+ companyId: string;
1702
+ messageId: string;
1703
+ status: TranscriptionStatus;
1704
+ /** Ausente em `pending`/`failed`/`unsupported`; vazio em `done` é silêncio já processado. */
1705
+ text?: string | null;
1706
+ language?: string | null;
1707
+ engine?: string | null;
1708
+ }
1709
+ declare class MessageRepository {
1710
+ private readonly db;
1711
+ constructor(db: MetaWhatsAppDatabase);
1712
+ insertMessage(params: InsertMessageParams): Promise<MessageRow | undefined>;
1713
+ updateMessageStatus(companyId: string, waMessageId: string, status: MessageStatus): Promise<MessageRow | undefined>;
1714
+ /**
1715
+ * Grava a transcrição endereçando pelo id da Meta, para quem só tem esse.
1716
+ *
1717
+ * Serve ao caso em que a transcrição acontece no próprio webhook — o grafo precisa do texto para
1718
+ * responder ao cliente, e jogar fora o que ele já pagou para transcrever significaria transcrever
1719
+ * o mesmo áudio uma segunda vez só para o painel ver.
1720
+ *
1721
+ * Devolve `undefined` quando não achou a mensagem: entrega duplicada e mensagem apagada são
1722
+ * corridas normais, não erro.
1723
+ */
1724
+ saveTranscriptionByWaMessageId(params: SaveTranscriptionByWaMessageIdParams): Promise<MessageRow | undefined>;
1725
+ findById(companyId: string, messageId: string): Promise<MessageRow | undefined>;
1726
+ /**
1727
+ * Grava o resultado da transcrição. Devolve `undefined` quando a mensagem não existe (apagada
1728
+ * entre o enfileiramento e a execução do job) — não é erro, é corrida normal.
1729
+ *
1730
+ * `text`/`language`/`engine` só são tocados quando informados: uma retentativa que volta a falhar
1731
+ * atualiza o status sem apagar a transcrição parcial de uma tentativa anterior que tenha vindo de
1732
+ * outro engine da cadeia.
1733
+ */
1734
+ saveTranscription(params: SaveTranscriptionParams): Promise<MessageRow | undefined>;
1735
+ listByConversation(params: ListMessagesParams$1): Promise<MessageRow[]>;
1736
+ }
1737
+
1738
+ declare const DEFAULT_FLOW_GRAPH_CACHE_TTL_SECONDS = 300;
1739
+ /**
1740
+ * Cache de leitura dos grafos de fluxo, com invalidação na publicação.
1741
+ *
1742
+ * TTL **e** invalidação explícita, e não um dos dois: só TTL deixaria o cliente andando no grafo
1743
+ * antigo até a chave expirar, logo depois de alguém corrigir o fluxo no editor; só invalidação
1744
+ * deixaria cache envenenado para sempre se um `delete` se perdesse (Redis reiniciando, deploy no
1745
+ * meio da escrita).
1746
+ *
1747
+ * Toda operação é tolerante a falha por decisão de projeto: cache é aceleração, não dependência.
1748
+ * Redis fora do ar tem que degradar para leitura no banco — que é exatamente o comportamento de
1749
+ * quem não configura cache nenhum — em vez de derrubar a conversa do cliente.
1750
+ */
1751
+ declare class FlowGraphCache {
1752
+ private readonly provider;
1753
+ private readonly ttlSeconds;
1754
+ constructor(provider: CacheInterface, ttlSeconds?: number);
1755
+ private keyFor;
1756
+ read(companyId: string, flowKey: string): Promise<FlowGraphData | undefined>;
1757
+ write(companyId: string, graph: FlowGraphData): Promise<void>;
1758
+ invalidate(companyId: string, flowKey: string): Promise<void>;
1759
+ }
1760
+
825
1761
  declare class InvalidFlowGraphError extends Error {
826
1762
  readonly validationMessage: string;
827
1763
  constructor(key: string, validationMessage: string);
@@ -831,7 +1767,8 @@ declare class OptimisticLockError extends Error {
831
1767
  }
832
1768
  declare class FlowGraphRepository {
833
1769
  private readonly db;
834
- constructor(db: BunSQLDatabase<AnyRelations | EmptyRelations>);
1770
+ private readonly cache?;
1771
+ constructor(db: MetaWhatsAppDatabase, cache?: FlowGraphCache | undefined);
835
1772
  get(companyId: string, key: string): Promise<FlowGraphData | undefined>;
836
1773
  list(companyId: string): Promise<FlowGraphSummary[]>;
837
1774
  private assertValidNodes;
@@ -846,48 +1783,130 @@ declare class FlowGraphRepository {
846
1783
 
847
1784
  declare class SettingsRepository {
848
1785
  private readonly db;
849
- constructor(db: BunSQLDatabase<AnyRelations | EmptyRelations>);
1786
+ constructor(db: MetaWhatsAppDatabase);
850
1787
  get(companyId: string): Promise<WhatsAppSettings>;
851
1788
  save(companyId: string, update: Partial<WhatsAppSettings>): Promise<WhatsAppSettings>;
852
1789
  resolveTemplateVariables(companyId: string, context: Record<string, unknown>): Promise<string[]>;
853
1790
  }
854
1791
 
855
- interface InsertMessageParams {
856
- companyId: string;
857
- sessionId: string;
858
- whatsappNumber: string;
859
- direction: MessageDirection;
860
- sender: MessageSender;
861
- agentUserId?: string | null;
862
- type: string;
863
- content?: string | null;
864
- payload?: Record<string, unknown> | null;
865
- waMessageId?: string | null;
866
- status?: MessageStatus | null;
867
- }
868
- interface ListMessagesParams$1 {
869
- companyId: string;
870
- sessionId: string;
871
- limit?: number;
872
- before?: string;
873
- }
874
- declare class MessageRepository {
875
- private readonly db;
876
- constructor(db: BunSQLDatabase<AnyRelations | EmptyRelations>);
877
- insertMessage(params: InsertMessageParams): Promise<MessageRow | undefined>;
878
- updateMessageStatus(companyId: string, waMessageId: string, status: MessageStatus): Promise<MessageRow | undefined>;
879
- listByConversation(params: ListMessagesParams$1): Promise<MessageRow[]>;
880
- }
881
-
882
1792
  type LogMessageParams = Omit<InsertMessageParams, 'sessionId'> & {
883
1793
  startState: SessionState;
884
1794
  };
1795
+ /**
1796
+ * O contrato mínimo de `@adatechnology/text-moderation`, declarado aqui em vez de importado.
1797
+ *
1798
+ * Assim o módulo não ganha dependência de pacote para um recurso opcional, e — mais importante —
1799
+ * moderação não fica amarrada a WhatsApp: o que atravessa esta fronteira é texto, e qualquer canal
1800
+ * que passe a escrever no transcript por este use case herda a marcação sem tocar nada aqui.
1801
+ */
1802
+ type MessageModerator = {
1803
+ inspect: (text: string) => {
1804
+ isOffensive: boolean;
1805
+ matchedTerms: readonly string[];
1806
+ };
1807
+ };
885
1808
  declare class LogMessageUseCase {
886
1809
  private readonly sessionRepository;
887
1810
  private readonly messageRepository;
888
1811
  private readonly realtime?;
889
- constructor(sessionRepository: SessionRepository, messageRepository: MessageRepository, realtime?: RealtimeNotifierInterface | undefined);
1812
+ private readonly moderator?;
1813
+ constructor(sessionRepository: SessionRepository, messageRepository: MessageRepository, realtime?: RealtimeNotifierInterface | undefined, moderator?: MessageModerator | undefined);
890
1814
  execute(params: LogMessageParams): Promise<MessageRow | undefined>;
1815
+ private moderationOf;
1816
+ }
1817
+
1818
+ interface LinkDocumentParams {
1819
+ companyId: string;
1820
+ sessionId: string;
1821
+ messageId?: string | null;
1822
+ uploadId: string;
1823
+ filename: string;
1824
+ mimeType: string;
1825
+ sizeBytes: number;
1826
+ sha256?: string | null;
1827
+ source: string;
1828
+ }
1829
+ interface ListDocumentsParams {
1830
+ companyId: string;
1831
+ sessionId: string;
1832
+ search?: string;
1833
+ /**
1834
+ * Origens aceitas, como lista explícita (`['agent', 'bot']`) e não como apelido de UI.
1835
+ *
1836
+ * Agrupamento tipo "Equipe" é vocabulário de tela e muda por produto; traduzir aqui obrigaria o
1837
+ * módulo a conhecer o rótulo de cada host. Quem recebe o apelido na borda é a rota.
1838
+ */
1839
+ sources?: readonly string[];
1840
+ sortDirection?: 'asc' | 'desc';
1841
+ page?: number;
1842
+ limit?: number;
1843
+ }
1844
+ interface ListCompanyDocumentsParams$1 {
1845
+ companyId: string;
1846
+ search?: string;
1847
+ sources?: readonly string[];
1848
+ sortDirection?: 'asc' | 'desc';
1849
+ page?: number;
1850
+ limit?: number;
1851
+ }
1852
+ interface CompanyDocumentRow {
1853
+ id: string;
1854
+ uploadId: string;
1855
+ filename: string;
1856
+ mimeType: string;
1857
+ sizeBytes: number;
1858
+ source: string;
1859
+ linkedAt: Date;
1860
+ whatsappNumber: string;
1861
+ }
1862
+ interface ListCompanyDocumentsResult {
1863
+ rows: CompanyDocumentRow[];
1864
+ total: number;
1865
+ }
1866
+ interface ListDocumentsResult {
1867
+ rows: DocumentRow[];
1868
+ /** Total no servidor, ANTES do corte de página — é o que permite calcular a última página. */
1869
+ total: number;
1870
+ }
1871
+ declare class DocumentRepository {
1872
+ private readonly db;
1873
+ constructor(db: MetaWhatsAppDatabase);
1874
+ /**
1875
+ * Idempotente por (companyId, uploadId), garantido pelo índice único e não por SELECT prévio: o
1876
+ * job de ingestão é reentregue por retry e duas tentativas concorrentes passariam as duas por uma
1877
+ * checagem, duplicando a linha no painel.
1878
+ *
1879
+ * Devolve `undefined` quando o documento já estava linkado.
1880
+ */
1881
+ link(params: LinkDocumentParams): Promise<DocumentRow | undefined>;
1882
+ listByConversation(params: ListDocumentsParams): Promise<ListDocumentsResult>;
1883
+ /**
1884
+ * A biblioteca da EMPRESA inteira, não de uma conversa.
1885
+ *
1886
+ * A busca casa nome do arquivo OU telefone da conversa — ver `companyDocumentSearch`.
1887
+ *
1888
+ * Faz join com `sessions` para carregar de qual conversa cada arquivo veio — numa lista global,
1889
+ * arquivo sem essa referência é inútil: o atendente vê "comprovante.pdf" e não sabe de quem.
1890
+ *
1891
+ * Ordena por `linkedAt` apoiada no índice `idx_documents_company_linked`, que já existia para a
1892
+ * varredura de retenção.
1893
+ */
1894
+ listByCompany(params: ListCompanyDocumentsParams$1): Promise<ListCompanyDocumentsResult>;
1895
+ /**
1896
+ * Um documento pela key do objeto. Serve para recuperar o nome original na hora de assinar o
1897
+ * download: a key é caminho no bucket e salvaria o arquivo com o id da Meta.
1898
+ */
1899
+ findByUploadId(companyId: string, uploadId: string): Promise<DocumentRow | undefined>;
1900
+ /**
1901
+ * Os objetos a apagar no storage antes de a linha sumir.
1902
+ *
1903
+ * Existe porque a cascata da FK apaga a linha e deixa o binário órfão: quem for apagar a conversa
1904
+ * precisa desta lista primeiro, senão paga armazenamento para sempre por arquivo inalcançável.
1905
+ */
1906
+ listUploadIdsBySession(companyId: string, sessionId: string): Promise<string[]>;
1907
+ /** Varredura de retenção por idade — o par é o mesmo cuidado com o objeto no storage. */
1908
+ listExpired(companyId: string, olderThan: Date, limit?: number): Promise<DocumentRow[]>;
1909
+ deleteById(companyId: string, id: string): Promise<void>;
891
1910
  }
892
1911
 
893
1912
  type SendTextParams = {
@@ -924,7 +1943,8 @@ declare class SendMessageUseCase {
924
1943
  private readonly sessionRepository;
925
1944
  private readonly logMessage;
926
1945
  private readonly objectStorage?;
927
- constructor(channel: ChannelAdapterInterface, sessionRepository: SessionRepository, logMessage: LogMessageUseCase, objectStorage?: ObjectStorageInterface | undefined);
1946
+ private readonly documentRepository?;
1947
+ constructor(channel: ChannelAdapterInterface, sessionRepository: SessionRepository, logMessage: LogMessageUseCase, objectStorage?: ObjectStorageInterface | undefined, documentRepository?: DocumentRepository | undefined);
928
1948
  private assertWithinWindow;
929
1949
  sendText(params: SendTextParams): Promise<MessageRow | undefined>;
930
1950
  sendMedia(params: SendMediaParams): Promise<MessageRow | undefined>;
@@ -977,6 +1997,143 @@ declare class ListMessagesUseCase {
977
1997
  execute(params: ListMessagesParams): Promise<MessageRow[]>;
978
1998
  }
979
1999
 
2000
+ type ListConversationDocumentsParams = {
2001
+ companyId: string;
2002
+ whatsappNumber: string;
2003
+ search?: string;
2004
+ /** Origens explícitas. O apelido de UI ("Equipe") é traduzido na borda HTTP, não aqui. */
2005
+ sources?: readonly string[];
2006
+ sortDirection?: 'asc' | 'desc';
2007
+ page?: number;
2008
+ limit?: number;
2009
+ };
2010
+ /**
2011
+ * O que o `ConversationDocumentsPanel` do conversations-ui consome. O shape é o do pacote de UI
2012
+ * (`ConversationDocument`), com `linkedAt` já em ISO para não obrigar cada host a serializar.
2013
+ */
2014
+ type ConversationDocumentView = {
2015
+ /**
2016
+ * O `uploadId` (key no storage), e NÃO o id da linha.
2017
+ *
2018
+ * É este valor que o consumidor devolve para pedir a URL assinada ou montar o zip, então expor o
2019
+ * UUID da tabela aqui fazia o download apontar para um objeto inexistente — falha que só aparece
2020
+ * no clique, porque a assinatura é gerada sem consultar o bucket.
2021
+ */
2022
+ id: string;
2023
+ filename: string;
2024
+ mimeType: string;
2025
+ sizeBytes: number;
2026
+ source: string;
2027
+ linkedAt: string;
2028
+ };
2029
+ /** Espelha o `ConversationDocumentPage` do conversations-ui: lista da página + total no servidor. */
2030
+ type ConversationDocumentsPage = {
2031
+ documents: ConversationDocumentView[];
2032
+ total: number;
2033
+ };
2034
+ declare class ListConversationDocumentsUseCase {
2035
+ private readonly sessionRepository;
2036
+ private readonly documentRepository;
2037
+ constructor(sessionRepository: SessionRepository, documentRepository: DocumentRepository);
2038
+ execute(params: ListConversationDocumentsParams): Promise<ConversationDocumentsPage>;
2039
+ }
2040
+
2041
+ type ListCompanyDocumentsParams = {
2042
+ companyId: string;
2043
+ search?: string;
2044
+ /** Origens explícitas. O apelido de UI ("Equipe") é traduzido na borda HTTP, não aqui. */
2045
+ sources?: readonly string[];
2046
+ sortDirection?: 'asc' | 'desc';
2047
+ page?: number;
2048
+ limit?: number;
2049
+ };
2050
+ /**
2051
+ * Um arquivo na biblioteca da empresa. Igual ao da conversa, mais `conversationId` — sem saber de
2052
+ * quem veio, uma lista global de anexos não responde nenhuma pergunta útil.
2053
+ */
2054
+ type CompanyDocumentView = {
2055
+ /** O `uploadId` (key no storage), pelo mesmo motivo do `ConversationDocumentView`. */
2056
+ id: string;
2057
+ conversationId: string;
2058
+ filename: string;
2059
+ mimeType: string;
2060
+ sizeBytes: number;
2061
+ source: string;
2062
+ linkedAt: string;
2063
+ };
2064
+ type CompanyDocumentsPage = {
2065
+ documents: CompanyDocumentView[];
2066
+ total: number;
2067
+ };
2068
+ /**
2069
+ * Biblioteca de arquivos de todas as conversas da empresa.
2070
+ *
2071
+ * Existe separada de `ListConversationDocumentsUseCase` porque a pergunta é outra: aquela parte de
2072
+ * uma conversa conhecida, esta varre a empresa e por isso precisa dizer de qual conversa cada
2073
+ * arquivo veio. Reaproveitar a primeira exigiria um `sessionId` opcional que muda o significado do
2074
+ * retorno — dois nomes claros custam menos que um parâmetro que dobra o comportamento.
2075
+ */
2076
+ declare class ListCompanyDocumentsUseCase {
2077
+ private readonly documentRepository;
2078
+ constructor(documentRepository: DocumentRepository);
2079
+ execute(params: ListCompanyDocumentsParams): Promise<CompanyDocumentsPage>;
2080
+ }
2081
+
2082
+ type DeleteConversationParams = {
2083
+ companyId: string;
2084
+ whatsappNumber: string;
2085
+ };
2086
+ type DeleteConversationResult = {
2087
+ /** Objetos efetivamente apagados no storage. */
2088
+ deletedObjects: number;
2089
+ /** Objetos que o storage recusou. A conversa NÃO é apagada quando isto é maior que zero. */
2090
+ failedObjects: readonly string[];
2091
+ };
2092
+ /**
2093
+ * Apaga a conversa e a mídia dela.
2094
+ *
2095
+ * A ordem é o ponto: **storage primeiro, banco depois**. A FK de `documents.session_id` é
2096
+ * `on delete cascade`, então apagar a sessão primeiro derrubaria as linhas e levaria embora a única
2097
+ * lista de `uploadId` existente — os binários ficariam órfãos, cobrados para sempre e inalcançáveis.
2098
+ *
2099
+ * Se algum objeto falhar, a conversa é preservada e o chamador recebe a lista. Apagar as linhas
2100
+ * "mesmo assim" transformaria uma falha visível e reexecutável em lixo silencioso no storage.
2101
+ */
2102
+ declare class DeleteConversationUseCase {
2103
+ private readonly sessionRepository;
2104
+ private readonly documentRepository;
2105
+ private readonly objectStorage?;
2106
+ constructor(sessionRepository: SessionRepository, documentRepository: DocumentRepository, objectStorage?: ObjectStorageInterface | undefined);
2107
+ execute(params: DeleteConversationParams): Promise<DeleteConversationResult>;
2108
+ }
2109
+
2110
+ type PurgeExpiredDocumentsParams = {
2111
+ companyId: string;
2112
+ /** Dias de retenção. O produto configura; o módulo não escolhe política de dado pessoal. */
2113
+ retentionDays: number;
2114
+ /** Teto por execução, para o job não segurar conexão nem storage por tempo indefinido. */
2115
+ batchSize?: number;
2116
+ /** Instante de referência — injetado para o teste não depender do relógio. */
2117
+ now?: Date;
2118
+ };
2119
+ type PurgeExpiredDocumentsResult = {
2120
+ purged: number;
2121
+ failed: readonly string[];
2122
+ };
2123
+ /**
2124
+ * Apaga documento vencido: objeto no storage primeiro, linha depois — a mesma ordem do
2125
+ * `DeleteConversationUseCase`, e pelo mesmo motivo.
2126
+ *
2127
+ * A linha só cai quando o objeto caiu. Contar como purgado sem ter apagado o binário deixaria lixo
2128
+ * pago no storage sem nenhum registro que o alcance depois: a linha era o único ponteiro.
2129
+ */
2130
+ declare class PurgeExpiredDocumentsUseCase {
2131
+ private readonly documentRepository;
2132
+ private readonly objectStorage?;
2133
+ constructor(documentRepository: DocumentRepository, objectStorage?: ObjectStorageInterface | undefined);
2134
+ execute(params: PurgeExpiredDocumentsParams): Promise<PurgeExpiredDocumentsResult>;
2135
+ }
2136
+
980
2137
  type ExportConversationParams = {
981
2138
  companyId: string;
982
2139
  whatsappNumber: string;
@@ -1098,6 +2255,57 @@ declare class FlowInterpreter {
1098
2255
  }): Promise<FlowRunResult>;
1099
2256
  }
1100
2257
 
2258
+ type FlowMediaLocation = {
2259
+ companyId: string;
2260
+ flowKey: string;
2261
+ nodeId: string;
2262
+ };
2263
+ type AttachFlowMediaParams = FlowMediaLocation & {
2264
+ uploadId: string;
2265
+ filename: string;
2266
+ mimeType: string;
2267
+ sizeBytes: number;
2268
+ caption?: string;
2269
+ sortOrder?: number;
2270
+ };
2271
+ type UpdateFlowMediaParams = {
2272
+ companyId: string;
2273
+ id: string;
2274
+ caption?: string | null;
2275
+ sortOrder?: number;
2276
+ active?: boolean;
2277
+ };
2278
+ declare class FlowMediaRepository {
2279
+ private readonly db;
2280
+ constructor(db: MetaWhatsAppDatabase);
2281
+ private locationFilter;
2282
+ listActive(location: FlowMediaLocation): Promise<FlowMediaRow[]>;
2283
+ listAll(location: FlowMediaLocation): Promise<FlowMediaRow[]>;
2284
+ /**
2285
+ * Anexa um arquivo já existente no storage ao nó.
2286
+ *
2287
+ * `onConflictDoUpdate` em vez de deixar estourar: reanexar o mesmo arquivo é clique repetido no
2288
+ * editor, e o esperado ali é atualizar a legenda/ordem — não um erro de índice único na cara de
2289
+ * quem está montando o fluxo.
2290
+ */
2291
+ attach(params: AttachFlowMediaParams): Promise<FlowMediaRow>;
2292
+ update(params: UpdateFlowMediaParams): Promise<FlowMediaRow | undefined>;
2293
+ /**
2294
+ * Desanexa do nó. Não toca no storage de propósito: o mesmo `uploadId` pode estar anexado a
2295
+ * outro nó ou a outro fluxo, e apagar o binário aqui quebraria os demais. Quem apaga objeto é o
2296
+ * host, que é dono da biblioteca de arquivos.
2297
+ */
2298
+ detach(params: {
2299
+ companyId: string;
2300
+ id: string;
2301
+ }): Promise<void>;
2302
+ detachRemovedNodes(params: {
2303
+ companyId: string;
2304
+ flowKey: string;
2305
+ existingNodeIds: string[];
2306
+ }): Promise<void>;
2307
+ }
2308
+
1101
2309
  interface NonceStoreInterface {
1102
2310
  setIfAbsent(key: string, ttlSeconds: number): Promise<boolean>;
1103
2311
  }
@@ -1128,11 +2336,13 @@ type ReceiveWebhookResult = {
1128
2336
  duplicate: boolean;
1129
2337
  messagesProcessed: number;
1130
2338
  statusesProcessed: number;
2339
+ ignoredForeignNumber: number;
1131
2340
  };
1132
2341
  declare class ReceiveWebhookUseCase {
1133
2342
  private readonly params;
1134
2343
  constructor(params: {
1135
2344
  appSecret: string;
2345
+ phoneNumberId: string;
1136
2346
  nonceStore: NonceStoreInterface;
1137
2347
  sessionRepository: SessionRepository;
1138
2348
  messageRepository: MessageRepository;
@@ -1146,6 +2356,39 @@ declare class ReceiveWebhookUseCase {
1146
2356
  private handleStatus;
1147
2357
  }
1148
2358
 
2359
+ /**
2360
+ * Política efetiva de transcrição de uma empresa.
2361
+ *
2362
+ * A separação que este arquivo existe para manter: **ambiente decide se é POSSÍVEL, settings decide
2363
+ * se é para FAZER.** A capacidade (engine, chave, storage que sabe reler) é injetada pelo host e é
2364
+ * por deploy — chave de API não vai para tabela de configuração de tenant. Já "transcrever ou não" e
2365
+ * "automático ou sob demanda" são decisão de operação de cada empresa, e pedir deploy para mudar
2366
+ * isso é o que transforma um interruptor em ticket.
2367
+ */
2368
+ type TranscriptionPolicy = {
2369
+ readonly isEnabled: boolean;
2370
+ readonly mode: TranscriptionMode;
2371
+ };
2372
+ type TranscriptionPolicyDefaults = {
2373
+ /** O que vale quando o painel não decidiu. Tipicamente vem do ambiente do host. */
2374
+ readonly isEnabled: boolean;
2375
+ readonly mode: TranscriptionMode;
2376
+ };
2377
+ type ResolveTranscriptionPolicyDependencies = {
2378
+ readonly settingsRepository: SettingsRepository;
2379
+ readonly defaults: TranscriptionPolicyDefaults;
2380
+ };
2381
+ /**
2382
+ * Resolve a política por empresa, com o padrão do host como base.
2383
+ *
2384
+ * Uma consulta a `settings` por áudio transcrito. Não é cacheado de propósito: é uma leitura por
2385
+ * chave primária, acontece uma vez por nota de voz (não por mensagem), e cachear introduziria a
2386
+ * pergunta "por quanto tempo o operador continua vendo o interruptor antigo depois de mexer nele" —
2387
+ * custo real, para economizar um índice único.
2388
+ */
2389
+ declare function createTranscriptionPolicyResolver(dependencies: ResolveTranscriptionPolicyDependencies): (companyId: string) => Promise<TranscriptionPolicy>;
2390
+ type TranscriptionPolicyResolver = ReturnType<typeof createTranscriptionPolicyResolver>;
2391
+
1149
2392
  type IngestInboundMediaParams = {
1150
2393
  companyId: string;
1151
2394
  messageId: string;
@@ -1156,13 +2399,52 @@ type IngestInboundMediaParams = {
1156
2399
  type IngestInboundMediaResult = {
1157
2400
  uploadId: string;
1158
2401
  alreadyIngested: boolean;
2402
+ /**
2403
+ * Só presente quando a transcrição automática rodou nesta execução. Ausente é o normal: mídia que
2404
+ * não é áudio, transcrição desligada, modo sob demanda, ou mídia já ingerida antes.
2405
+ */
2406
+ transcription?: {
2407
+ status: TranscriptionStatus;
2408
+ };
2409
+ };
2410
+ /**
2411
+ * Transcrição durante a ingestão — o modo `auto`.
2412
+ *
2413
+ * Entra aqui, e não em use-case separado, por um motivo só: neste ponto o buffer do áudio ACABOU de
2414
+ * ser baixado e está em memória. Transcrever fora daqui custaria um segundo download do storage por
2415
+ * áudio, e o `TranscribeAudioUseCase` existe justamente para esse caso (sob demanda e retomada).
2416
+ */
2417
+ type IngestTranscriptionOptions = {
2418
+ transcriber: AudioTranscriber;
2419
+ messageRepository: MessageRepository;
2420
+ /**
2421
+ * Política POR EMPRESA, resolvida a cada áudio. Não é um `mode` fixo porque o interruptor mora nas
2422
+ * configurações da empresa: um valor capturado na construção do use-case congelaria a escolha até
2423
+ * o próximo deploy, e o worker é um processo longo — o operador mexeria no painel e nada mudaria.
2424
+ */
2425
+ resolvePolicy: TranscriptionPolicyResolver;
2426
+ languageHint?: string;
2427
+ hooks?: Pick<MetaWhatsAppHooks, 'onTranscriptionDeferred'>;
1159
2428
  };
1160
2429
  declare class IngestInboundMediaUseCase {
1161
2430
  private readonly db;
1162
2431
  private readonly channel;
1163
2432
  private readonly objectStorage;
1164
- constructor(db: BunSQLDatabase<AnyRelations | EmptyRelations>, channel: ChannelAdapterInterface, objectStorage: ObjectStorageInterface);
2433
+ private readonly documentRepository?;
2434
+ private readonly transcription?;
2435
+ constructor(db: MetaWhatsAppDatabase, channel: ChannelAdapterInterface, objectStorage: ObjectStorageInterface, documentRepository?: DocumentRepository | undefined, transcription?: IngestTranscriptionOptions | undefined);
1165
2436
  execute(params: IngestInboundMediaParams): Promise<IngestInboundMediaResult>;
2437
+ /**
2438
+ * Transcreve o áudio recém-baixado, quando o modo é `auto`.
2439
+ *
2440
+ * **Nunca propaga erro.** Neste ponto o binário já está no storage e já entrou na biblioteca da
2441
+ * conversa: deixar uma falha de transcrição subir marcaria a ingestão inteira como falha, e o
2442
+ * retry do host baixaria de novo da Meta um arquivo que está salvo — gastando banda para reproduzir
2443
+ * um efeito que já aconteceu. O status fica gravado na mensagem e o `onTranscriptionDeferred`
2444
+ * avisa quem sabe reenfileirar.
2445
+ */
2446
+ private transcribeIfAuto;
2447
+ private recordTranscriptionFailure;
1166
2448
  }
1167
2449
  declare function extractMediaDescriptor(message: MessageRow): {
1168
2450
  sourceMediaId: string;
@@ -1170,6 +2452,105 @@ declare function extractMediaDescriptor(message: MessageRow): {
1170
2452
  filename?: string;
1171
2453
  } | undefined;
1172
2454
 
2455
+ /**
2456
+ * Storage com leitura garantida. `getObject` é opcional no contrato, então quem monta este use-case
2457
+ * precisa provar que o método existe — sem os bytes não há o que transcrever, e um use-case que
2458
+ * sempre falha é pior do que a ausência ser visível no tipo.
2459
+ */
2460
+ type ReadableObjectStorage = ObjectStorageInterface & {
2461
+ getObject: NonNullable<ObjectStorageInterface['getObject']>;
2462
+ };
2463
+ type TranscribeAudioParams = {
2464
+ companyId: string;
2465
+ messageId: string;
2466
+ /**
2467
+ * Refaz mesmo com transcrição já salva. Serve ao "transcrever de novo" depois de trocar de engine
2468
+ * — sem isto, um resultado ruim do engine antigo ficaria congelado para sempre.
2469
+ */
2470
+ force?: boolean;
2471
+ };
2472
+ type TranscribeAudioResult = {
2473
+ status: TranscriptionStatus;
2474
+ text: string | null;
2475
+ language: string | null;
2476
+ engine: string | null;
2477
+ /** `true` quando devolveu o que já estava salvo, sem gastar cota. */
2478
+ alreadyTranscribed: boolean;
2479
+ };
2480
+ type TranscribeAudioDependencies = {
2481
+ messageRepository: MessageRepository;
2482
+ objectStorage: ReadableObjectStorage;
2483
+ transcriber: AudioTranscriber;
2484
+ /**
2485
+ * Política por empresa. Ausente, a transcrição sob demanda não consulta configuração nenhuma e
2486
+ * atende sempre — que é o comportamento de quem controla o liga/desliga só por ambiente.
2487
+ */
2488
+ resolvePolicy?: TranscriptionPolicyResolver;
2489
+ /** ISO 639-1 do produto. Informar corta a detecção do Whisper e evita pt-BR curto virar espanhol. */
2490
+ languageHint?: string;
2491
+ hooks?: Pick<MetaWhatsAppHooks, 'onTranscriptionDeferred'>;
2492
+ };
2493
+ /**
2494
+ * Transcreve o áudio de UMA mensagem já persistida e ingerida.
2495
+ *
2496
+ * Serve aos dois modos: é o que o painel chama no botão "transcrever" (`onDemand`) e é o que o host
2497
+ * chama ao retomar um `pending` reenfileirado. O modo `auto` não passa por aqui — ele transcreve
2498
+ * dentro da ingestão, onde o buffer já está em memória e não custa um segundo download.
2499
+ *
2500
+ * Idempotente por `transcription_status`: chamar de novo num `'done'` devolve o que está salvo em
2501
+ * vez de gastar cota transcrevendo o mesmo áudio.
2502
+ */
2503
+ declare class TranscribeAudioUseCase {
2504
+ private readonly dependencies;
2505
+ constructor(dependencies: TranscribeAudioDependencies);
2506
+ execute(params: TranscribeAudioParams): Promise<TranscribeAudioResult>;
2507
+ private transcribeBuffer;
2508
+ /**
2509
+ * Carimba o motivo antes de propagar. O status é o que impede os dois desperdícios simétricos:
2510
+ * reprocessar para sempre um codec impossível, e desistir de um áudio que só esbarrou na cota.
2511
+ */
2512
+ private persistFailure;
2513
+ }
2514
+ declare function resolveFailureStatus(error: unknown): TranscriptionStatus;
2515
+
2516
+ /**
2517
+ * Guarda um arquivo gravado no simulador e devolve o id que o webhook vai referenciar.
2518
+ *
2519
+ * Existe como use-case para o host só precisar da ROTA: receber o corpo, chamar isto, devolver o
2520
+ * `mediaId`. A parte que erra — onde gravar, com que chave, como marcar o id para o adaptador
2521
+ * reconhecer depois — fica aqui, num lugar só, e não em cada produto.
2522
+ *
2523
+ * O SDK para exatamente na porta do HTTP: registrar endpoint é do host, e um pacote que abrisse rota
2524
+ * no servidor de quem o instala decidiria caminho, autenticação e versionamento no lugar dele.
2525
+ */
2526
+ type StorePreviewMediaParams = {
2527
+ companyId: string;
2528
+ /** Bytes do arquivo. Quem converte de base64 é a rota — o use-case não conhece transporte. */
2529
+ buffer: Buffer;
2530
+ mimeType: string;
2531
+ filename?: string;
2532
+ };
2533
+ type StorePreviewMediaResult = {
2534
+ /** Já com o prefixo: é isto que o simulador manda no webhook. */
2535
+ mediaId: string;
2536
+ uploadId: string;
2537
+ };
2538
+ declare class StorePreviewMediaUseCase {
2539
+ private readonly objectStorage;
2540
+ /**
2541
+ * Fonte do sufixo único da chave. Injetada porque o módulo não escolhe gerador de id — e porque
2542
+ * um teste precisa de chave previsível.
2543
+ */
2544
+ private readonly generateKeySuffix;
2545
+ constructor(objectStorage: ObjectStorageInterface,
2546
+ /**
2547
+ * Fonte do sufixo único da chave. Injetada porque o módulo não escolhe gerador de id — e porque
2548
+ * um teste precisa de chave previsível.
2549
+ */
2550
+ generateKeySuffix: () => string);
2551
+ execute(params: StorePreviewMediaParams): Promise<StorePreviewMediaResult>;
2552
+ }
2553
+
1173
2554
  interface MetaWhatsAppModuleConfig {
1174
2555
  phoneNumberId: string;
1175
2556
  accessToken: string;
@@ -1181,15 +2562,60 @@ interface MetaWhatsAppModuleConfig {
1181
2562
  }
1182
2563
  interface MetaWhatsAppModuleFeatures {
1183
2564
  flowEngine?: boolean;
2565
+ flowGraphCache?: boolean | {
2566
+ ttlSeconds?: number;
2567
+ };
2568
+ /**
2569
+ * Aceita mídia do simulador de conversa — o que faz o microfone aparecer no preview do cliente.
2570
+ *
2571
+ * **Desligado por omissão, e a decisão é consciente.** Ligado, o canal passa a aceitar id que não
2572
+ * veio da Meta: `preview-upload:<chave>` faz o servidor ler aquele objeto do storage. Em ambiente
2573
+ * de simulação isso é o recurso; em produção é leitura arbitrária do bucket por webhook forjado.
2574
+ *
2575
+ * Exige `providers.objectStorage` com `getObject` — sem os bytes não há o que devolver, e o flag é
2576
+ * ignorado em vez de produzir um canal que falha na primeira nota de voz.
2577
+ */
2578
+ previewMedia?: boolean;
2579
+ }
2580
+ /**
2581
+ * Transcrição de áudio. Ausente = desligada, e as colunas ficam nulas ("não avaliado").
2582
+ *
2583
+ * `mode` é a decisão de produto que este objeto existe para carregar: `auto` transcreve toda nota de
2584
+ * voz recebida, na ingestão, onde o buffer já está em memória; `onDemand` só transcreve quando o
2585
+ * atendente pede, gastando cota apenas com áudio que alguém vai ler de fato.
2586
+ */
2587
+ interface MetaWhatsAppTranscriptionConfig {
2588
+ transcriber: AudioTranscriber;
2589
+ /**
2590
+ * PADRÃO, não decisão final: vale para as empresas que não mexeram no interruptor do painel. As
2591
+ * configurações por empresa (`settings.transcriptionMode`) têm precedência.
2592
+ *
2593
+ * Padrão `onDemand` — o modo que não gasta cota sem alguém pedir.
2594
+ */
2595
+ mode?: TranscriptionMode;
2596
+ /**
2597
+ * PADRÃO de ligado/desligado para empresas sem escolha registrada. `true` — injetar o transcritor
2598
+ * já é a declaração de que o host quer o recurso; quem controla por empresa usa o painel.
2599
+ */
2600
+ isEnabledByDefault?: boolean;
2601
+ /** ISO 639-1 do produto (ex.: `'pt'`). Corta a detecção de idioma do engine. */
2602
+ languageHint?: string;
1184
2603
  }
1185
2604
  interface MetaWhatsAppModuleProviders {
1186
2605
  objectStorage?: ObjectStorageInterface;
2606
+ cache?: CacheInterface;
1187
2607
  realtime?: RealtimeNotifierInterface;
1188
2608
  subjectResolver?: SubjectResolverInterface;
1189
2609
  catalog?: CatalogPort;
2610
+ moderator?: MessageModerator;
2611
+ /**
2612
+ * Converte nota de voz em texto. Exige `objectStorage` com `getObject` para o modo sob demanda —
2613
+ * transcrever um áudio já salvo significa ler os bytes de volta.
2614
+ */
2615
+ transcription?: MetaWhatsAppTranscriptionConfig;
1190
2616
  }
1191
2617
  interface CreateMetaWhatsAppModuleParams {
1192
- db: BunSQLDatabase<AnyRelations | EmptyRelations>;
2618
+ db: MetaWhatsAppDatabase;
1193
2619
  config: MetaWhatsAppModuleConfig;
1194
2620
  nonceStore: NonceStoreInterface;
1195
2621
  startState?: SessionState;
@@ -1207,10 +2633,31 @@ declare function createMetaWhatsAppModule(params: CreateMetaWhatsAppModuleParams
1207
2633
  release: ReleaseConversationUseCase;
1208
2634
  list: ListConversationsUseCase;
1209
2635
  listMessages: ListMessagesUseCase;
2636
+ listDocuments: ListConversationDocumentsUseCase;
2637
+ listCompanyDocuments: ListCompanyDocumentsUseCase;
2638
+ delete: DeleteConversationUseCase;
2639
+ purgeExpiredDocuments: PurgeExpiredDocumentsUseCase;
1210
2640
  export: ExportConversationUseCase;
2641
+ transcribeAudio: TranscribeAudioUseCase | undefined;
1211
2642
  repository: SessionRepository;
2643
+ messageRepository: MessageRepository;
2644
+ documentRepository: DocumentRepository;
1212
2645
  };
2646
+ /**
2647
+ * `undefined` = o host não injetou transcritor, e nenhuma configuração de empresa muda isso: a
2648
+ * capacidade não existe. Presente, `resolvePolicy` responde o que vale para uma empresa —
2649
+ * é o que a rota de configurações usa para dizer ao painel se desenha o interruptor.
2650
+ */
2651
+ transcription: {
2652
+ defaultMode: TranscriptionMode;
2653
+ resolvePolicy: (companyId: string) => Promise<TranscriptionPolicy>;
2654
+ } | undefined;
1213
2655
  settings: SettingsRepository;
2656
+ /**
2657
+ * `undefined` quando o recurso não está ligado (ou falta storage legível). O host consulta a
2658
+ * ausência para não registrar a rota de upload — e o preview, sem a rota, esconde o microfone.
2659
+ */
2660
+ previewMedia: StorePreviewMediaUseCase | undefined;
1214
2661
  webhook: {
1215
2662
  receive: ReceiveWebhookUseCase;
1216
2663
  verifyChallenge: (query: {
@@ -1229,14 +2676,42 @@ declare function createMetaWhatsAppModule(params: CreateMetaWhatsAppModuleParams
1229
2676
  delete: DeleteFlowGraphUseCase;
1230
2677
  livePositions: GetLiveFlowPositionsUseCase;
1231
2678
  repository: FlowGraphRepository;
2679
+ mediaRepository: FlowMediaRepository;
1232
2680
  } | undefined;
1233
2681
  catalog: CatalogPort | undefined;
1234
2682
  };
1235
2683
  type MetaWhatsAppModule = ReturnType<typeof createMetaWhatsAppModule>;
1236
2684
 
2685
+ /**
2686
+ * Leitura de mídia do simulador de conversa.
2687
+ *
2688
+ * **Atrás de flag de propósito, e não ligado por omissão.** Aceitar id que não veio da Meta é
2689
+ * exatamente o que um webhook forjado exploraria: bastaria mandar `preview-upload:<chave>` para
2690
+ * fazer o servidor ler um objeto arbitrário do storage e devolvê-lo. Num ambiente de simulação isso
2691
+ * é o recurso; em produção é leitura arbitrária. Quem liga assume, e a decisão fica visível no
2692
+ * lugar onde o módulo é montado.
2693
+ */
2694
+ type PreviewMediaSupport = {
2695
+ readonly isEnabled: boolean;
2696
+ readonly objectStorage: ObjectStorageInterface & {
2697
+ getObject: NonNullable<ObjectStorageInterface['getObject']>;
2698
+ };
2699
+ /** Mime a devolver, já que o storage guarda bytes e não o tipo. Padrão `audio/ogg`. */
2700
+ readonly defaultMimeType?: string;
2701
+ };
1237
2702
  declare class WhatsAppChannelAdapter implements ChannelAdapterInterface {
1238
2703
  private readonly messages;
1239
- constructor(messages: WhatsAppMessageProvider);
2704
+ /**
2705
+ * Ausente, o adaptador se comporta como sempre: todo id vai para a Graph API. É o que garante
2706
+ * que atualizar o pacote não abre nada em quem não pediu.
2707
+ */
2708
+ private readonly previewMedia?;
2709
+ constructor(messages: WhatsAppMessageProvider,
2710
+ /**
2711
+ * Ausente, o adaptador se comporta como sempre: todo id vai para a Graph API. É o que garante
2712
+ * que atualizar o pacote não abre nada em quem não pediu.
2713
+ */
2714
+ previewMedia?: PreviewMediaSupport | undefined);
1240
2715
  private translateErrors;
1241
2716
  sendText(to: string, body: string): Promise<{
1242
2717
  externalMessageId: string | null;
@@ -1269,13 +2744,38 @@ declare class WhatsAppChannelAdapter implements ChannelAdapterInterface {
1269
2744
  }): Promise<{
1270
2745
  externalMessageId: string | null;
1271
2746
  }>;
2747
+ sendInteractiveButtons(params: {
2748
+ to: string;
2749
+ body: string;
2750
+ buttons: {
2751
+ id: string;
2752
+ title: string;
2753
+ }[];
2754
+ }): Promise<{
2755
+ externalMessageId: string | null;
2756
+ }>;
2757
+ /**
2758
+ * Busca o binário da mídia — da Meta, ou do storage quando o id é do simulador.
2759
+ *
2760
+ * O desvio acontece ANTES de qualquer chamada de rede: id do simulador não existe na Meta, e
2761
+ * tentar buscá-lo lá renderia um 404 confuso em vez do áudio que o operador acabou de gravar.
2762
+ */
1272
2763
  fetchMediaAsBase64(mediaId: string): Promise<{
1273
2764
  data: string;
1274
2765
  mimeType: string;
1275
2766
  }>;
1276
2767
  }
1277
2768
 
1278
- declare function runMetaWhatsAppMigrations<TRelations extends AnyRelations = EmptyRelations>(db: BunSQLDatabase<TRelations>): Promise<void>;
2769
+ declare const META_WHATSAPP_MIGRATIONS_TABLE = "meta_whatsapp_migrations";
2770
+ declare function metaWhatsAppMigrationsFolder(): string;
2771
+ type RunMetaWhatsAppMigrationsParams = {
2772
+ db: MetaWhatsAppDatabase;
2773
+ migrate: (db: never, config: {
2774
+ migrationsFolder: string;
2775
+ migrationsTable?: string;
2776
+ }) => Promise<void>;
2777
+ };
2778
+ declare function runMetaWhatsAppMigrations(params: RunMetaWhatsAppMigrationsParams): Promise<void>;
1279
2779
 
1280
2780
  type SseListener = (event: string, payload: Record<string, unknown>) => void;
1281
2781
  interface TicketStoreInterface {
@@ -1303,4 +2803,42 @@ declare function redeemSseTicket(store: TicketStoreInterface, ticket: string): P
1303
2803
  whatsappNumber: string;
1304
2804
  } | null>;
1305
2805
 
1306
- export { type CreateFlowGraphParams, CreateFlowGraphUseCase, type CreateMetaWhatsAppModuleParams, DeleteFlowGraphUseCase, type ExportConversationParams, type ExportConversationResult, ExportConversationUseCase, FlowGraphRepository, type FlowGraphRow, FlowInterpreter, type FlowRunResult, type FlowStepInput, type FlowStepResult, GetFlowGraphUseCase, GetLiveFlowPositionsUseCase, type IngestInboundMediaParams, type IngestInboundMediaResult, IngestInboundMediaUseCase, type InsertMessageParams, InvalidFlowGraphError, type ListConversationsFilters, type ListConversationsParams, ListConversationsUseCase, ListFlowGraphsUseCase, type ListMessagesParams, ListMessagesUseCase, type LogMessageParams, LogMessageUseCase, MessageRepository, type MessageRow, type MetaWhatsAppModule, type MetaWhatsAppModuleConfig, type MetaWhatsAppModuleFeatures, type MetaWhatsAppModuleProviders, type NewFlowGraphRow, type NewMessageRow, type NewSessionRow, type NewSettingsRow, type NonceStoreInterface, OptimisticLockError, type RealtimeRelay, type ReceiveWebhookParams, type ReceiveWebhookResult, ReceiveWebhookUseCase, type ReleaseConversationParams, ReleaseConversationUseCase, type ListMessagesParams$1 as RepositoryListMessagesParams, type SaveFlowGraphParams, SaveFlowGraphUseCase, type SendMediaParams, SendMessageUseCase, type SendTemplateParams, type SendTextParams, SessionRepository, type SessionRow, SettingsRepository, type SettingsRow, SseHub, type SseListener, type TakeoverConversationParams, TakeoverConversationUseCase, type TicketStoreInterface, WEBHOOK_NONCE_TTL_SECONDS, WhatsAppChannelAdapter, claimWebhookDelivery, createMetaWhatsAppModule, extractMediaDescriptor, flowGraphs, issueSseTicket, messages, metaWhatsAppSchema, redeemSseTicket, runMetaWhatsAppMigrations, sessions, settings, verifyWebhookChallenge, verifyWebhookSignature };
2806
+ /**
2807
+ * Porta de escrita no transcript, e não a classe `LogMessageUseCase`.
2808
+ *
2809
+ * Exigir a classe amarraria a action a quem já guarda as mensagens nas tabelas do módulo — um host
2810
+ * em migração, com o transcript ainda no schema dele, não conseguiria usar a única action built-in
2811
+ * sem gravar o envio numa tabela que o painel dele não lê. O que a action precisa é só de um lugar
2812
+ * para registrar o que saiu.
2813
+ */
2814
+ type FlowMediaTranscriptLogger = {
2815
+ execute(params: LogMessageParams): Promise<unknown>;
2816
+ };
2817
+ type CreateSendMediaActionParams = {
2818
+ flowMediaRepository: FlowMediaRepository;
2819
+ objectStorage: ObjectStorageInterface & {
2820
+ getObject: NonNullable<ObjectStorageInterface['getObject']>;
2821
+ };
2822
+ logMessage: FlowMediaTranscriptLogger;
2823
+ startState: SessionState;
2824
+ onError?: (error: unknown, details: {
2825
+ flowKey: string;
2826
+ nodeId: string;
2827
+ uploadId: string;
2828
+ }) => void;
2829
+ };
2830
+ /**
2831
+ * Action `send_media`: ao passar pelo nó, envia os arquivos que a biblioteca tem anexados a ele.
2832
+ *
2833
+ * É a única action built-in que o módulo implementa de ponta a ponta — as outras
2834
+ * (`handoff`, `send_product_list`) dependem de regra de negócio do produto. Esta não: "mandar
2835
+ * estes arquivos ao chegar aqui" é comportamento de canal, e replicá-la em cada host seria
2836
+ * copiar o mesmo código com os mesmos bugs.
2837
+ *
2838
+ * O nó não guarda os arquivos em `actionParams` de propósito. Se guardasse, trocar o material
2839
+ * exigiria editar e republicar o grafo — e o ponto todo é o contrário: quem cuida do conteúdo
2840
+ * troca o arquivo na biblioteca e o fluxo continua igual.
2841
+ */
2842
+ declare function createSendMediaAction(params: CreateSendMediaActionParams): FlowActionHandler;
2843
+
2844
+ export { type AttachFlowMediaParams, type AudioTranscriber, type CompanyDocumentView, type CompanyDocumentsPage, type ConversationDocumentView, type ConversationDocumentsPage, type CreateFlowGraphParams, CreateFlowGraphUseCase, type CreateMetaWhatsAppModuleParams, type CreateSendMediaActionParams, DEFAULT_FLOW_GRAPH_CACHE_TTL_SECONDS, type DeleteConversationParams, type DeleteConversationResult, DeleteConversationUseCase, DeleteFlowGraphUseCase, DocumentRepository, type DocumentRow, type DrizzleMigrateFunction, type ExportConversationParams, type ExportConversationResult, ExportConversationUseCase, FlowGraphCache, FlowGraphRepository, type FlowGraphRow, FlowInterpreter, type FlowMediaLocation, FlowMediaRepository, type FlowMediaRow, type FlowMediaTranscriptLogger, type FlowRunResult, type FlowStepInput, type FlowStepResult, GetFlowGraphUseCase, GetLiveFlowPositionsUseCase, type IngestInboundMediaParams, type IngestInboundMediaResult, IngestInboundMediaUseCase, type IngestTranscriptionOptions, type InsertMessageParams, InvalidFlowGraphError, type LinkDocumentParams, type ListCompanyDocumentsParams, ListCompanyDocumentsUseCase, type ListConversationDocumentsParams, ListConversationDocumentsUseCase, type ListConversationsFilters, type ListConversationsParams, ListConversationsUseCase, type ListDocumentsParams, type ListDocumentsResult, ListFlowGraphsUseCase, type ListMessagesParams, ListMessagesUseCase, type LogMessageParams, LogMessageUseCase, META_WHATSAPP_MIGRATIONS_TABLE, type MessageModerator, MessageRepository, type MessageRow, type MetaWhatsAppDatabase, type MetaWhatsAppModule, type MetaWhatsAppModuleConfig, type MetaWhatsAppModuleFeatures, type MetaWhatsAppModuleProviders, type MetaWhatsAppTranscriptionConfig, type NewDocumentRow, type NewFlowGraphRow, type NewFlowMediaRow, type NewMessageRow, type NewSessionRow, type NewSettingsRow, type NonceStoreInterface, OptimisticLockError, type PreviewMediaSupport, type PurgeExpiredDocumentsParams, type PurgeExpiredDocumentsResult, PurgeExpiredDocumentsUseCase, type RealtimeRelay, type ReceiveWebhookParams, type ReceiveWebhookResult, ReceiveWebhookUseCase, type ReleaseConversationParams, ReleaseConversationUseCase, type ListMessagesParams$1 as RepositoryListMessagesParams, type ResolveTranscriptionPolicyDependencies, type RunMetaWhatsAppMigrationsParams, type SaveFlowGraphParams, SaveFlowGraphUseCase, type SaveTranscriptionByWaMessageIdParams, type SaveTranscriptionParams, type SendMediaParams, SendMessageUseCase, type SendTemplateParams, type SendTextParams, SessionRepository, type SessionRow, SettingsRepository, type SettingsRow, SseHub, type SseListener, type StorePreviewMediaParams, type StorePreviewMediaResult, StorePreviewMediaUseCase, TRANSCRIPTION_MODE, TRANSCRIPTION_STATUS, type TakeoverConversationParams, TakeoverConversationUseCase, type TicketStoreInterface, type TranscribeAudioDependencies, type TranscribeAudioParams, type TranscribeAudioResult, TranscribeAudioUseCase, type TranscriptionPolicy, type TranscriptionPolicyDefaults, type TranscriptionPolicyResolver, type TranscriptionStatus, type UpdateFlowMediaParams, WEBHOOK_NONCE_TTL_SECONDS, WhatsAppChannelAdapter, claimWebhookDelivery, createMetaWhatsAppModule, createSendMediaAction, createTranscriptionPolicyResolver, documents, extractMediaDescriptor, flowGraphs, flowMedia, isAudioMimeType, isRetriableTranscriptionError, isUnsupportedTranscriptionError, issueSseTicket, messages, metaWhatsAppMigrationsFolder, metaWhatsAppSchema, redeemSseTicket, resolveFailureStatus, runMetaWhatsAppMigrations, sessions, settings, transcriptionRetryAfterSeconds, verifyWebhookChallenge, verifyWebhookSignature };