evo360-types 1.3.376 → 1.3.378

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.
@@ -98,16 +98,25 @@ export type IHubiaConversationMode = z.infer<typeof zHubiaConversationModeSchema
98
98
  // ───────── evo-hubia-rules (deterministic rule layer) ─────────
99
99
  //
100
100
  // Camada de regras determinísticas avaliada pelo motor `evo-hubia-rules`
101
- // (ver cloud-functions/docs/evo-hubia-rules/). Hooks suportados:
102
- // - `pre_llm` (v1.0) : avalia ANTES do orchestrator LLM rodar.
103
- // - `post_llm` (v1.1) : avalia DEPOIS do orchestrator e ANTES do envio
104
- // outbound; cobre safety/governance (content gate,
105
- // circuit breaker, salvaguarda pós-tool).
101
+ // (ver cloud-functions/docs/evo-hubia-rules/). A regra é identificada pela
102
+ // combinação ortogonal (trigger `when` × `phase`):
103
+ // - `when=inbound_message` + `phase=pre_llm` (v1.0) : avalia ANTES do
104
+ // orchestrator LLM rodar, na mensagem do paciente.
105
+ // - `when=llm_completed` + `phase=post_llm` (feat-026): avalia DEPOIS do
106
+ // orchestrator e ANTES do envio outbound; cobre
107
+ // safety/governance (content gate, circuit breaker).
108
+ // - `when=outbound_message` + `phase=pre_llm` (feat-027): avalia DEPOIS que
109
+ // uma mensagem outbound foi enviada ao paciente
110
+ // (reativo pós-fato, qualquer origem: LLM, operador,
111
+ // n8n, system). Executa side-effects; não muta a msg.
112
+ // - `when=outbound_message` + `phase=post_llm` : RESERVADO — habilitado
113
+ // quando "LLM em outbound" for liberado (fora de
114
+ // escopo na v1.0). Schema aceita, runtime não dispara.
106
115
  //
107
- // Matriz phase × outcome × when (enforced pelo superRefine de
108
- // `zHubiaRuleSchema` abaixo):
109
- // - pre_llm + when=inbound_message + outcome {stop,to_llm,to_llm_with_context}
110
- // - post_llm + when=llm_completed + outcome = stop
116
+ // Matriz when × outcome (enforced pelo superRefine de `zHubiaRuleSchema`):
117
+ // - inbound_message + outcome ∈ {stop, to_llm, to_llm_with_context}
118
+ // - llm_completed + outcome = stop
119
+ // - outbound_message + outcome = stop (to_llm reservado p/ LLM-em-outbound)
111
120
  //
112
121
  // As regras moram em `binding.rules[]` — o binding É o cruzamento canal⨯
113
122
  // departamento, então o escopo de departamento é implícito.
@@ -115,12 +124,20 @@ export type IHubiaConversationMode = z.infer<typeof zHubiaConversationModeSchema
115
124
  /** Fase de avaliação. Tipos TS em src/types/evo-hub-ia/v1/. */
116
125
  export const zHubiaRulePhaseSchema = z.enum(["pre_llm", "post_llm"]);
117
126
 
118
- export const zHubiaRuleTriggerSchema = z.enum(["inbound_message", "llm_completed"]);
127
+ export const zHubiaRuleTriggerSchema = z.enum(["inbound_message", "llm_completed", "outbound_message"]);
119
128
 
120
129
  export const zHubiaRuleOutcomeSchema = z.enum(["stop", "to_llm", "to_llm_with_context"]);
121
130
 
122
131
  export const zHubiaRuleAppliesToSchema = z.enum(["real_message", "kickoff", "any"]);
123
132
 
133
+ /** Filtro por origem da mensagem outbound (apenas `when=outbound_message`).
134
+ * - `all` : qualquer origem dispara a regra.
135
+ * - `llm_only` : só mensagens geradas pelo LLM.
136
+ * - `non_system` : exclui mensagens sintéticas do sistema.
137
+ * - `all_except_kickoff` : default — exclui apenas msgs de kickoff de
138
+ * transferência (proteção contra loop). */
139
+ export const zHubiaOutboundSourceSchema = z.enum(["all", "llm_only", "non_system", "all_except_kickoff"]);
140
+
124
141
  export const zHubiaConditionOpSchema = z.enum([
125
142
  "exists", "not_exists",
126
143
  "is_empty", "is_not_empty",
@@ -206,6 +223,9 @@ export const zHubiaConditionGroupSchema = z.object({
206
223
  export const zHubiaRuleScopeSchema = z.object({
207
224
  applies_to: zHubiaRuleAppliesToSchema.optional(),
208
225
  provider: z.enum(["chatbee", "hub-waba"]).optional(),
226
+ /** Apenas `when=outbound_message`: filtra por origem da msg outbound.
227
+ * Default runtime quando ausente: `all_except_kickoff`. */
228
+ outbound_source: zHubiaOutboundSourceSchema.optional(),
209
229
  }).partial();
210
230
 
211
231
  /** Uma ação a executar via ToolRegistry. `input` aceita templating
@@ -250,9 +270,12 @@ export const zHubiaRuleSchema = z.object({
250
270
  /** Aborta sequência de ações no primeiro erro. */
251
271
  stop_actions_on_error: z.boolean().default(true),
252
272
  }).passthrough().superRefine((rule, ctx) => {
253
- // Matriz phase × outcome × when. pre_llm é permissivo (back-compat com
254
- // regras v1.0); post_llm é restrito a outcome=stop + when=llm_completed
255
- // (decisão C2 em features/feat-026-hubia-rules-v1-1/decisions.md).
273
+ // Matriz when × phase × outcome. inbound_message+pre_llm é permissivo
274
+ // (back-compat com regras v1.0); as demais combinações são restritas.
275
+ //
276
+ // - post_llm → outcome=stop + when=llm_completed (feat-026 C2)
277
+ // - outbound_message → outcome=stop (to_llm reservado p/ LLM-em-outbound,
278
+ // fora de escopo na feat-027)
256
279
  if (rule.phase === "post_llm") {
257
280
  if (rule.outcome !== "stop") {
258
281
  ctx.addIssue({
@@ -269,6 +292,13 @@ export const zHubiaRuleSchema = z.object({
269
292
  });
270
293
  }
271
294
  }
295
+ if (rule.when === "outbound_message" && rule.outcome !== "stop") {
296
+ ctx.addIssue({
297
+ code: z.ZodIssueCode.custom,
298
+ path: ["outcome"],
299
+ message: "when=outbound_message aceita apenas outcome=stop (to_llm será habilitado quando LLM em outbound for liberado)",
300
+ });
301
+ }
272
302
  });
273
303
 
274
304
  // ───────── AI Binding (department → AI agent routing) ─────────
@@ -975,12 +975,12 @@ export declare const zQuestionResponseSchema: z.ZodObject<{
975
975
  answer: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
976
976
  date: z.ZodOptional<z.ZodDate>;
977
977
  }, "strip", z.ZodTypeAny, {
978
- questionId: string;
979
978
  answer: string | string[];
979
+ questionId: string;
980
980
  date?: Date | undefined;
981
981
  }, {
982
- questionId: string;
983
982
  answer: string | string[];
983
+ questionId: string;
984
984
  date?: Date | undefined;
985
985
  }>;
986
986
  export declare const zSurveyResponseSchema: z.ZodObject<{
@@ -998,12 +998,12 @@ export declare const zSurveyResponseSchema: z.ZodObject<{
998
998
  answer: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
999
999
  date: z.ZodOptional<z.ZodDate>;
1000
1000
  }, "strip", z.ZodTypeAny, {
1001
- questionId: string;
1002
1001
  answer: string | string[];
1002
+ questionId: string;
1003
1003
  date?: Date | undefined;
1004
1004
  }, {
1005
- questionId: string;
1006
1005
  answer: string | string[];
1006
+ questionId: string;
1007
1007
  date?: Date | undefined;
1008
1008
  }>, "many">>;
1009
1009
  }, "strip", z.ZodTypeAny, {
@@ -1016,8 +1016,8 @@ export declare const zSurveyResponseSchema: z.ZodObject<{
1016
1016
  updated_at?: Date | null | undefined;
1017
1017
  deleted_at?: Date | null | undefined;
1018
1018
  responses?: {
1019
- questionId: string;
1020
1019
  answer: string | string[];
1020
+ questionId: string;
1021
1021
  date?: Date | undefined;
1022
1022
  }[] | undefined;
1023
1023
  }, {
@@ -1030,8 +1030,8 @@ export declare const zSurveyResponseSchema: z.ZodObject<{
1030
1030
  updated_at?: Date | null | undefined;
1031
1031
  deleted_at?: Date | null | undefined;
1032
1032
  responses?: {
1033
- questionId: string;
1034
1033
  answer: string | string[];
1034
+ questionId: string;
1035
1035
  date?: Date | undefined;
1036
1036
  }[] | undefined;
1037
1037
  }>;
@@ -1064,12 +1064,12 @@ export declare const zSurveySubmissionSchema: z.ZodObject<{
1064
1064
  answer: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
1065
1065
  date: z.ZodOptional<z.ZodDate>;
1066
1066
  }, "strip", z.ZodTypeAny, {
1067
- questionId: string;
1068
1067
  answer: string | string[];
1068
+ questionId: string;
1069
1069
  date?: Date | undefined;
1070
1070
  }, {
1071
- questionId: string;
1072
1071
  answer: string | string[];
1072
+ questionId: string;
1073
1073
  date?: Date | undefined;
1074
1074
  }>, "many">>;
1075
1075
  }, "strip", z.ZodTypeAny, {
@@ -1082,8 +1082,8 @@ export declare const zSurveySubmissionSchema: z.ZodObject<{
1082
1082
  updated_at?: Date | null | undefined;
1083
1083
  deleted_at?: Date | null | undefined;
1084
1084
  responses?: {
1085
- questionId: string;
1086
1085
  answer: string | string[];
1086
+ questionId: string;
1087
1087
  date?: Date | undefined;
1088
1088
  }[] | undefined;
1089
1089
  }, {
@@ -1096,8 +1096,8 @@ export declare const zSurveySubmissionSchema: z.ZodObject<{
1096
1096
  updated_at?: Date | null | undefined;
1097
1097
  deleted_at?: Date | null | undefined;
1098
1098
  responses?: {
1099
- questionId: string;
1100
1099
  answer: string | string[];
1100
+ questionId: string;
1101
1101
  date?: Date | undefined;
1102
1102
  }[] | undefined;
1103
1103
  }>, "many">>;
@@ -1127,8 +1127,8 @@ export declare const zSurveySubmissionSchema: z.ZodObject<{
1127
1127
  updated_at?: Date | null | undefined;
1128
1128
  deleted_at?: Date | null | undefined;
1129
1129
  responses?: {
1130
- questionId: string;
1131
1130
  answer: string | string[];
1131
+ questionId: string;
1132
1132
  date?: Date | undefined;
1133
1133
  }[] | undefined;
1134
1134
  }[] | undefined;
@@ -1154,8 +1154,8 @@ export declare const zSurveySubmissionSchema: z.ZodObject<{
1154
1154
  updated_at?: Date | null | undefined;
1155
1155
  deleted_at?: Date | null | undefined;
1156
1156
  responses?: {
1157
- questionId: string;
1158
1157
  answer: string | string[];
1158
+ questionId: string;
1159
1159
  date?: Date | undefined;
1160
1160
  }[] | undefined;
1161
1161
  }[] | undefined;
@@ -1427,12 +1427,12 @@ export declare const zSurveyDeploymentSchema: z.ZodObject<{
1427
1427
  answer: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>;
1428
1428
  date: z.ZodOptional<z.ZodDate>;
1429
1429
  }, "strip", z.ZodTypeAny, {
1430
- questionId: string;
1431
1430
  answer: string | string[];
1431
+ questionId: string;
1432
1432
  date?: Date | undefined;
1433
1433
  }, {
1434
- questionId: string;
1435
1434
  answer: string | string[];
1435
+ questionId: string;
1436
1436
  date?: Date | undefined;
1437
1437
  }>, "many">>;
1438
1438
  }, "strip", z.ZodTypeAny, {
@@ -1445,8 +1445,8 @@ export declare const zSurveyDeploymentSchema: z.ZodObject<{
1445
1445
  updated_at?: Date | null | undefined;
1446
1446
  deleted_at?: Date | null | undefined;
1447
1447
  responses?: {
1448
- questionId: string;
1449
1448
  answer: string | string[];
1449
+ questionId: string;
1450
1450
  date?: Date | undefined;
1451
1451
  }[] | undefined;
1452
1452
  }, {
@@ -1459,8 +1459,8 @@ export declare const zSurveyDeploymentSchema: z.ZodObject<{
1459
1459
  updated_at?: Date | null | undefined;
1460
1460
  deleted_at?: Date | null | undefined;
1461
1461
  responses?: {
1462
- questionId: string;
1463
1462
  answer: string | string[];
1463
+ questionId: string;
1464
1464
  date?: Date | undefined;
1465
1465
  }[] | undefined;
1466
1466
  }>, "many">>;
@@ -1490,8 +1490,8 @@ export declare const zSurveyDeploymentSchema: z.ZodObject<{
1490
1490
  updated_at?: Date | null | undefined;
1491
1491
  deleted_at?: Date | null | undefined;
1492
1492
  responses?: {
1493
- questionId: string;
1494
1493
  answer: string | string[];
1494
+ questionId: string;
1495
1495
  date?: Date | undefined;
1496
1496
  }[] | undefined;
1497
1497
  }[] | undefined;
@@ -1517,8 +1517,8 @@ export declare const zSurveyDeploymentSchema: z.ZodObject<{
1517
1517
  updated_at?: Date | null | undefined;
1518
1518
  deleted_at?: Date | null | undefined;
1519
1519
  responses?: {
1520
- questionId: string;
1521
1520
  answer: string | string[];
1521
+ questionId: string;
1522
1522
  date?: Date | undefined;
1523
1523
  }[] | undefined;
1524
1524
  }[] | undefined;
@@ -1615,8 +1615,8 @@ export declare const zSurveyDeploymentSchema: z.ZodObject<{
1615
1615
  updated_at?: Date | null | undefined;
1616
1616
  deleted_at?: Date | null | undefined;
1617
1617
  responses?: {
1618
- questionId: string;
1619
1618
  answer: string | string[];
1619
+ questionId: string;
1620
1620
  date?: Date | undefined;
1621
1621
  }[] | undefined;
1622
1622
  }[] | undefined;
@@ -1712,8 +1712,8 @@ export declare const zSurveyDeploymentSchema: z.ZodObject<{
1712
1712
  updated_at?: Date | null | undefined;
1713
1713
  deleted_at?: Date | null | undefined;
1714
1714
  responses?: {
1715
- questionId: string;
1716
1715
  answer: string | string[];
1716
+ questionId: string;
1717
1717
  date?: Date | undefined;
1718
1718
  }[] | undefined;
1719
1719
  }[] | undefined;
@@ -18,6 +18,8 @@ export interface IMessageCall {
18
18
  duration_s?: number;
19
19
  end_reason?: string;
20
20
  }
21
+ export type CallMediaState = 'idle' | 'offer_ready' | 'answering' | 'answered' | 'connected' | 'ended';
22
+ export type CallTerminatedBy = 'patient' | 'agent' | 'system';
21
23
  export interface ICallSession extends IFireDoc {
22
24
  model_ver: number;
23
25
  provider_call_id: string;
@@ -38,4 +40,22 @@ export interface ICallSession extends IFireDoc {
38
40
  duration_s?: number;
39
41
  timeline_at: Date;
40
42
  last_event_at: Date;
43
+ claimed_by_user_id?: string;
44
+ claimed_by_name?: string;
45
+ claimed_at?: Date;
46
+ claim_expires_at?: Date;
47
+ accepted_by_user_id?: string;
48
+ accepted_at?: Date;
49
+ media_state?: CallMediaState;
50
+ browser_session_id?: string;
51
+ terminated_by?: CallTerminatedBy;
52
+ failure_code?: number;
53
+ failure_source?: string;
54
+ }
55
+ export interface ICallSignalRemote {
56
+ provider_call_id: string;
57
+ sdp_type: 'offer' | 'answer';
58
+ sdp: string;
59
+ source: 'meta';
60
+ created_at: Date;
41
61
  }
@@ -7,10 +7,9 @@ import type { MessageDirection } from "../thread-message";
7
7
  export type CallProviderDirection = 'USER_INITIATED' | 'BUSINESS_INITIATED';
8
8
 
9
9
  // Status de negócio normalizado da chamada.
10
- // Fase 1 (feat-029) produz apenas: ringing | missed | rejected | failed | completed.
11
- // Os demais (pre_accepted/accepted/connected/terminated) são reservados para a Fase 2
12
- // (voz via WebRTC) e existem aqui para a state machine de precedência ser estável
13
- // sem exigir republish do evo360-types quando a Fase 2 chegar.
10
+ // Fase 1 (feat-029) produz: ringing | missed | rejected | failed | completed.
11
+ // Os demais (pre_accepted/accepted/connected/terminated) são usados na Fase 2
12
+ // (voz via WebRTC, atendimento humano ao vivo).
14
13
  export type CallStatus =
15
14
  | 'ringing'
16
15
  | 'pre_accepted'
@@ -45,11 +44,23 @@ export interface IMessageCall {
45
44
  end_reason?: string;
46
45
  }
47
46
 
47
+ // ── Call media state (Fase 2 — atendimento ao vivo via WebRTC) ──
48
+
49
+ // Estado da mídia na perspectiva do nosso atendimento (browser do operador).
50
+ // Distinto de CallStatus (status de negócio da chamada). Governa a UI do cliente.
51
+ export type CallMediaState =
52
+ | 'idle' // sem mídia
53
+ | 'offer_ready' // SDP offer da Meta disponível para o operador (inbound)
54
+ | 'answering' // operador gerou answer / aguardando connect da Meta
55
+ | 'answered' // accept/connect enviado à Meta
56
+ | 'connected' // mídia fluindo
57
+ | 'ended'; // mídia encerrada
58
+
59
+ export type CallTerminatedBy = 'patient' | 'agent' | 'system';
60
+
48
61
  // ── Call Session (entidade canônica — fonte de verdade) ──
49
62
 
50
63
  // Path: tenants/{tenant}/apps/evo-chat/call_sessions/{provider_call_id}
51
- // Fase 1 = MÍNIMO. Campos operacionais da Fase 2 (claim/sdp refs/agent/presence)
52
- // NÃO devem ser adicionados aqui agora.
53
64
  export interface ICallSession extends IFireDoc {
54
65
  model_ver: number;
55
66
  provider_call_id: string; // wacid.* (também é o doc id)
@@ -71,11 +82,44 @@ export interface ICallSession extends IFireDoc {
71
82
 
72
83
  // Semântica de tempo.
73
84
  started_at?: Date; // chamada iniciada no WhatsApp (connect ts)
74
- connected_at?: Date; // mídia atendida Fase 2 (não setado na Fase 1)
85
+ connected_at?: Date; // mídia atendida (Fase 2)
75
86
  ended_at?: Date; // terminate
76
87
  duration_s?: number;
77
88
 
78
89
  // Ordenação/observação na timeline.
79
90
  timeline_at: Date; // primeiro timestamp de provider observado
80
91
  last_event_at: Date; // último timestamp de provider observado
92
+
93
+ // ── Fase 2 — atendimento ao vivo (WebRTC) ──
94
+ // Lock/claim: impede duas secretárias atenderem a mesma chamada.
95
+ claimed_by_user_id?: string;
96
+ claimed_by_name?: string;
97
+ claimed_at?: Date;
98
+ claim_expires_at?: Date;
99
+ // Operador que de fato atendeu a mídia.
100
+ accepted_by_user_id?: string;
101
+ accepted_at?: Date;
102
+ // Estado da mídia (governa a UI do cliente).
103
+ media_state?: CallMediaState;
104
+ // Identificador da sessão de browser que está conduzindo a mídia (1 aba ativa).
105
+ browser_session_id?: string;
106
+ // Encerramento.
107
+ terminated_by?: CallTerminatedBy;
108
+ failure_code?: number;
109
+ failure_source?: string;
110
+ }
111
+
112
+ // ── Sinalização WebRTC (relay de SDP) ──
113
+ // Doc: call_sessions/{provider_call_id}/signaling/remote
114
+ // Carrega APENAS o SDP REMOTO (vindo da Meta) que o browser do operador precisa
115
+ // consumir: offer no inbound, answer no outbound. O SDP gerado pelo browser
116
+ // (answer no inbound / offer no outbound) NUNCA é gravado aqui — vai por endpoint
117
+ // autenticado direto para a Meta. SDP é dado sensível e efêmero.
118
+ export interface ICallSignalRemote {
119
+ provider_call_id: string;
120
+ sdp_type: 'offer' | 'answer';
121
+ sdp: string;
122
+ // 'meta' = veio da Meta (único caso persistido).
123
+ source: 'meta';
124
+ created_at: Date;
81
125
  }
@@ -23,9 +23,18 @@ export interface ICallDeflectionConfig {
23
23
  only_outside_business_hours?: boolean;
24
24
  cooldown_minutes?: number;
25
25
  }
26
+ export interface ICallOutboundPermissionConfig {
27
+ enabled: boolean;
28
+ request_template?: {
29
+ name: string;
30
+ language: string;
31
+ };
32
+ }
26
33
  export interface ICallsChannelConfig {
27
34
  enabled: boolean;
28
35
  deflection?: ICallDeflectionConfig;
36
+ inbound_voice_enabled?: boolean;
37
+ outbound_permission?: ICallOutboundPermissionConfig;
29
38
  }
30
39
  export interface IChannel extends IFireDoc {
31
40
  model_ver: number;
@@ -32,10 +32,21 @@ export interface ICallDeflectionConfig {
32
32
  cooldown_minutes?: number; // hardening leve (notificação repetida)
33
33
  }
34
34
 
35
+ // Permissão para ligação outbound (business-initiated) — Fase 2.
36
+ // Antes de discar, a clínica precisa de permissão do usuário; quando ausente,
37
+ // envia-se um HSM com componente CALL_PERMISSION_REQUEST (template aprovado).
38
+ export interface ICallOutboundPermissionConfig {
39
+ enabled: boolean;
40
+ // Template HSM com botão/ação CALL_PERMISSION_REQUEST.
41
+ request_template?: { name: string; language: string };
42
+ }
43
+
35
44
  export interface ICallsChannelConfig {
36
45
  enabled: boolean;
37
46
  deflection?: ICallDeflectionConfig;
38
- // outbound_permission?: ICallOutboundPermissionConfig; // Fase 2 — não definir agora
47
+ // Fase 2 — voz ao vivo via WebRTC.
48
+ inbound_voice_enabled?: boolean; // permite atender chamada inbound no web-app
49
+ outbound_permission?: ICallOutboundPermissionConfig;
39
50
  }
40
51
 
41
52
  // ── Channel (evo-chat v3) ──
@@ -21,5 +21,13 @@ export interface IChatContact extends IFireDoc {
21
21
  wa_id?: string | null;
22
22
  provider?: 'chatbee' | 'hub-waba' | string;
23
23
  channel_ids?: string[];
24
+ call_permission?: ICallPermissionState;
24
25
  [key: string]: unknown;
25
26
  }
27
+ export interface ICallPermissionState {
28
+ status: 'granted' | 'denied' | 'none';
29
+ source?: 'user_action' | 'automatic';
30
+ is_permanent?: boolean;
31
+ expires_at?: string | number;
32
+ updated_at?: string;
33
+ }
@@ -29,5 +29,21 @@ export interface IChatContact extends IFireDoc {
29
29
  provider?: 'chatbee' | 'hub-waba' | string;
30
30
  channel_ids?: string[];
31
31
 
32
+ // ── call permission (feat-029 Fase 2) ──
33
+ // Última permissão de ligação conhecida deste contato (espelho local; a fonte
34
+ // de verdade é a Meta via GET /{phone_number_id}/call_permissions). Atualizado
35
+ // ao receber a interactive call_permission_reply.
36
+ call_permission?: ICallPermissionState;
37
+
32
38
  [key: string]: unknown; // index signature
33
39
  }
40
+
41
+ // Estado de permissão de ligação outbound (business-initiated) para um contato.
42
+ export interface ICallPermissionState {
43
+ status: 'granted' | 'denied' | 'none';
44
+ source?: 'user_action' | 'automatic';
45
+ is_permanent?: boolean;
46
+ // ISO 8601 ou epoch (segundos) — quando a permissão temporária expira.
47
+ expires_at?: string | number;
48
+ updated_at?: string;
49
+ }
@@ -13,6 +13,8 @@ export declare const THREAD_MESSAGES_COLLECTION = "messages";
13
13
  export declare const TICKETS_COLLECTION = "tickets";
14
14
  export declare const INBOXES_COLLECTION = "inboxes";
15
15
  export declare const CALL_SESSIONS_COLLECTION = "call_sessions";
16
+ export declare const CALL_SIGNALING_COLLECTION = "signaling";
17
+ export declare const CALL_SIGNAL_REMOTE_DOC = "remote";
16
18
  export declare const HubWabaCollections: {
17
19
  readonly TEMPLATES: "waba-templates";
18
20
  readonly QUICK_REPLIES: "quick-replies";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WABA_CHANNEL_INDEX_PATH = exports.WABA_SETUP_PATH = exports.HubWabaCollections = exports.CALL_SESSIONS_COLLECTION = exports.INBOXES_COLLECTION = exports.TICKETS_COLLECTION = exports.THREAD_MESSAGES_COLLECTION = exports.THREADS_COLLECTION = exports.CHANNELS_COLLECTION = exports.CHATBEE_CHANNELS_COLLECTION = exports.HSM_MESSAGES_COLLECTION = exports.PROTOCOLS_COLLECTION = exports.CONTACTS_COLLECTION = exports.TICKET_CLOSE_TYPES_COLLECTION = exports.TICKET_CLOSES_COLLECTION = exports.TICKET_CLOSES = exports.CHAT_DICS_COLLECTION = exports.EVO_CHAT_APP = void 0;
3
+ exports.WABA_CHANNEL_INDEX_PATH = exports.WABA_SETUP_PATH = exports.HubWabaCollections = exports.CALL_SIGNAL_REMOTE_DOC = exports.CALL_SIGNALING_COLLECTION = exports.CALL_SESSIONS_COLLECTION = exports.INBOXES_COLLECTION = exports.TICKETS_COLLECTION = exports.THREAD_MESSAGES_COLLECTION = exports.THREADS_COLLECTION = exports.CHANNELS_COLLECTION = exports.CHATBEE_CHANNELS_COLLECTION = exports.HSM_MESSAGES_COLLECTION = exports.PROTOCOLS_COLLECTION = exports.CONTACTS_COLLECTION = exports.TICKET_CLOSE_TYPES_COLLECTION = exports.TICKET_CLOSES_COLLECTION = exports.TICKET_CLOSES = exports.CHAT_DICS_COLLECTION = exports.EVO_CHAT_APP = void 0;
4
4
  //EVO Chat Application Doc
5
5
  exports.EVO_CHAT_APP = "evo-chat";
6
6
  //dictionaries
@@ -23,6 +23,8 @@ exports.THREAD_MESSAGES_COLLECTION = "messages"; // subcollection de threads
23
23
  exports.TICKETS_COLLECTION = "tickets";
24
24
  exports.INBOXES_COLLECTION = "inboxes";
25
25
  exports.CALL_SESSIONS_COLLECTION = "call_sessions"; // entidade canônica de chamadas (feat-029)
26
+ exports.CALL_SIGNALING_COLLECTION = "signaling"; // subcoleção de call_sessions p/ relay de SDP (feat-029 Fase 2)
27
+ exports.CALL_SIGNAL_REMOTE_DOC = "remote"; // doc único: SDP remoto (da Meta) que o browser consome
26
28
  // hub-waba template subcollection (under channels)
27
29
  exports.HubWabaCollections = {
28
30
  TEMPLATES: 'waba-templates',
@@ -26,6 +26,8 @@ export const THREAD_MESSAGES_COLLECTION = "messages"; // subcollection de thread
26
26
  export const TICKETS_COLLECTION = "tickets";
27
27
  export const INBOXES_COLLECTION = "inboxes";
28
28
  export const CALL_SESSIONS_COLLECTION = "call_sessions"; // entidade canônica de chamadas (feat-029)
29
+ export const CALL_SIGNALING_COLLECTION = "signaling"; // subcoleção de call_sessions p/ relay de SDP (feat-029 Fase 2)
30
+ export const CALL_SIGNAL_REMOTE_DOC = "remote"; // doc único: SDP remoto (da Meta) que o browser consome
29
31
 
30
32
  // hub-waba template subcollection (under channels)
31
33
  export const HubWabaCollections = {
@@ -30,8 +30,17 @@ export interface IMessageLocation {
30
30
  name?: string;
31
31
  address?: string;
32
32
  }
33
+ export type InteractiveMessageType = 'button_reply' | 'list_reply' | 'call_permission_reply' | 'call_permission_request';
34
+ /** Resposta do paciente a um pedido de permissão de ligação (WhatsApp Calling API). */
35
+ export interface ICallPermissionReply {
36
+ response?: 'accept' | 'reject';
37
+ is_permanent?: boolean;
38
+ /** Unix timestamp (segundos) — presente em permissões temporárias aceitas. */
39
+ expiration_timestamp?: number | string;
40
+ response_source?: 'user_action' | 'automatic';
41
+ }
33
42
  export interface IMessageInteractive {
34
- type: 'button_reply' | 'list_reply';
43
+ type: InteractiveMessageType | string;
35
44
  button_reply?: {
36
45
  id: string;
37
46
  title: string;
@@ -41,6 +50,7 @@ export interface IMessageInteractive {
41
50
  title: string;
42
51
  description?: string;
43
52
  };
53
+ call_permission_reply?: ICallPermissionReply;
44
54
  }
45
55
  export interface IMessageReaction {
46
56
  message_id: string;
@@ -48,10 +48,26 @@ export interface IMessageLocation {
48
48
 
49
49
  // ── Message interactive ──
50
50
 
51
+ export type InteractiveMessageType =
52
+ | 'button_reply'
53
+ | 'list_reply'
54
+ | 'call_permission_reply'
55
+ | 'call_permission_request';
56
+
57
+ /** Resposta do paciente a um pedido de permissão de ligação (WhatsApp Calling API). */
58
+ export interface ICallPermissionReply {
59
+ response?: 'accept' | 'reject';
60
+ is_permanent?: boolean;
61
+ /** Unix timestamp (segundos) — presente em permissões temporárias aceitas. */
62
+ expiration_timestamp?: number | string;
63
+ response_source?: 'user_action' | 'automatic';
64
+ }
65
+
51
66
  export interface IMessageInteractive {
52
- type: 'button_reply' | 'list_reply';
67
+ type: InteractiveMessageType | string;
53
68
  button_reply?: { id: string; title: string };
54
69
  list_reply?: { id: string; title: string; description?: string };
70
+ call_permission_reply?: ICallPermissionReply;
55
71
  }
56
72
 
57
73
  // ── Message reaction ──
@@ -1,26 +1,41 @@
1
1
  /** Fase de avaliação.
2
2
  * - `pre_llm` (v1.0) : avalia antes do orchestrator LLM.
3
3
  * - `post_llm` (v1.1) : avalia depois do orchestrator e antes do envio
4
- * outbound (safety/governance). */
4
+ * outbound (safety/governance).
5
+ * Ortogonal ao `when` (trigger): regras outbound (feat-027) usam
6
+ * `when=outbound_message + phase=pre_llm`. O par
7
+ * `outbound_message + post_llm` fica reservado p/ LLM-em-outbound futuro. */
5
8
  export type IHubiaRulePhase = "pre_llm" | "post_llm";
6
- /** Gatilho que dispara a avaliação. Correlacionado com `phase`:
7
- * pre_llm inbound_message; post_llm → llm_completed (validado pelo
8
- * superRefine de `zHubiaRuleSchema`). */
9
- export type IHubiaRuleTrigger = "inbound_message" | "llm_completed";
9
+ /** Gatilho que dispara a avaliação. Combinações válidas com `phase`
10
+ * (validado pelo superRefine de `zHubiaRuleSchema`):
11
+ * - `inbound_message` + pre_llm : mensagem do paciente (v1.0).
12
+ * - `llm_completed` + post_llm : turno do LLM concluído (feat-026).
13
+ * - `outbound_message` + pre_llm : mensagem enviada ao paciente, reativo
14
+ * pós-fato (feat-027). */
15
+ export type IHubiaRuleTrigger = "inbound_message" | "llm_completed" | "outbound_message";
10
16
  /** Desfecho do turno após a regra disparar:
11
17
  * - `stop` — finaliza turno; em pre_llm pula o LLM,
12
- * em post_llm bloqueia o envio outbound (único
13
- * outcome permitido em post_llm).
18
+ * em post_llm bloqueia o envio outbound, em
19
+ * outbound_message apenas registra trace + executa
20
+ * actions (msg já saiu). Único outcome permitido
21
+ * em post_llm e outbound_message.
14
22
  * - `to_llm` — segue para o orchestrator normalmente
15
- * (apenas pre_llm).
23
+ * (apenas inbound_message + pre_llm).
16
24
  * - `to_llm_with_context` — segue para o orchestrator com trace das ações
17
- * injetado como bloco de sistema (apenas pre_llm).
25
+ * injetado como bloco de sistema (apenas
26
+ * inbound_message + pre_llm).
18
27
  * Quando o LLM está desligado no binding (default_mode `human_only`/`blocked`),
19
28
  * `to_llm`/`to_llm_with_context` degradam para "cai pro humano". */
20
29
  export type IHubiaRuleOutcome = "stop" | "to_llm" | "to_llm_with_context";
21
30
  /** Tipo de batch ao qual a regra se aplica. `real_message` (default) ignora
22
31
  * a mensagem de kickoff do sistema — proteção contra loop de transferência. */
23
32
  export type IHubiaRuleAppliesTo = "real_message" | "kickoff" | "any";
33
+ /** Filtro por origem da mensagem outbound (apenas `when=outbound_message`).
34
+ * - `all` : qualquer origem dispara.
35
+ * - `llm_only` : só mensagens do LLM.
36
+ * - `non_system` : exclui mensagens sintéticas do sistema.
37
+ * - `all_except_kickoff` : default — exclui apenas kickoff de transferência. */
38
+ export type IHubiaOutboundSource = "all" | "llm_only" | "non_system" | "all_except_kickoff";
24
39
  /** Operadores suportados pelas condições.
25
40
  *
26
41
  * `in_schedule` / `not_in_schedule` esperam `value: IHubiaSchedule` e
@@ -79,6 +94,9 @@ export interface IHubiaConditionGroup {
79
94
  export interface IHubiaRuleScope {
80
95
  applies_to?: IHubiaRuleAppliesTo;
81
96
  provider?: "chatbee" | "hub-waba";
97
+ /** Apenas `when=outbound_message`: filtra por origem da msg outbound.
98
+ * Default runtime quando ausente: `all_except_kickoff`. */
99
+ outbound_source?: IHubiaOutboundSource;
82
100
  }
83
101
  /** Uma ação a executar via ToolRegistry. `input` aceita templating
84
102
  * `{{fact.path}}` resolvido em runtime pelo facts provider. */