evo360-types 1.3.405 → 1.3.408

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.
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.zAutomationDryRunRequestSchema = exports.zHubAutomationConfigSchema = exports.zAutomationRoutineSchema = exports.zAutomationBranchModeSchema = exports.zAutomationBranchSchema = exports.zAutomationOutputSchema = exports.zAutomationHumanTaskOutputSchema = exports.zAutomationAutoTaskOutputSchema = exports.zAutomationExecuteAtSchema = exports.zAutomationConditionGroupSchema = exports.zAutomationConditionSchema = exports.zAutomationOperatorSchema = exports.zAutomationSelectionSchema = exports.zAutomationAppointmentSelectionSchema = exports.zAutomationDateWindowSchema = exports.zAutomationDateOffsetModeSchema = exports.zAutomationTriggerSchema = exports.zAutomationCronTriggerSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const zod_schemas_1 = require("../evo-task/zod-schemas");
6
+ // ------------------------------------------------------
7
+ // Trigger (F1: cron only)
8
+ // ------------------------------------------------------
9
+ exports.zAutomationCronTriggerSchema = zod_1.z.object({
10
+ type: zod_1.z.literal("cron"),
11
+ cron: zod_1.z.object({
12
+ expression: zod_1.z.string().min(1),
13
+ timezone: zod_1.z.string().optional(),
14
+ }),
15
+ });
16
+ exports.zAutomationTriggerSchema = exports.zAutomationCronTriggerSchema;
17
+ // ------------------------------------------------------
18
+ // Selection (F1: appointment target only)
19
+ // ------------------------------------------------------
20
+ exports.zAutomationDateOffsetModeSchema = zod_1.z.enum(["calendar", "business"]);
21
+ exports.zAutomationDateWindowSchema = zod_1.z.object({
22
+ offset_days: zod_1.z.number().int(), // may be negative (retroactive routines)
23
+ offset_mode: exports.zAutomationDateOffsetModeSchema,
24
+ });
25
+ exports.zAutomationAppointmentSelectionSchema = zod_1.z.object({
26
+ target: zod_1.z.literal("appointment"),
27
+ appointment: zod_1.z.object({
28
+ calendar_ids: zod_1.z.array(zod_1.z.string()).optional(),
29
+ date_window: exports.zAutomationDateWindowSchema,
30
+ status_in: zod_1.z.array(zod_1.z.string()).optional(),
31
+ status_base_in: zod_1.z.array(zod_1.z.string()).optional(),
32
+ appointment_type_not_in: zod_1.z.array(zod_1.z.string()).optional(),
33
+ }),
34
+ });
35
+ exports.zAutomationSelectionSchema = exports.zAutomationAppointmentSelectionSchema;
36
+ // ------------------------------------------------------
37
+ // Conditions (recursive AND/OR groups via z.lazy)
38
+ // ------------------------------------------------------
39
+ exports.zAutomationOperatorSchema = zod_1.z.enum([
40
+ "eq",
41
+ "neq",
42
+ "in",
43
+ "not_in",
44
+ "exists",
45
+ "not_exists",
46
+ "is_true",
47
+ "is_false",
48
+ ]);
49
+ exports.zAutomationConditionSchema = zod_1.z.object({
50
+ fact: zod_1.z.string().min(1),
51
+ operator: exports.zAutomationOperatorSchema,
52
+ value: zod_1.z.unknown().optional(),
53
+ });
54
+ exports.zAutomationConditionGroupSchema = zod_1.z.lazy(() => zod_1.z.object({
55
+ combinator: zod_1.z.enum(["and", "or"]),
56
+ conditions: zod_1.z.array(zod_1.z.union([exports.zAutomationConditionSchema, exports.zAutomationConditionGroupSchema])),
57
+ }));
58
+ // ------------------------------------------------------
59
+ // Outputs (auto Task | human Task)
60
+ // ------------------------------------------------------
61
+ exports.zAutomationExecuteAtSchema = zod_1.z.discriminatedUnion("rule", [
62
+ zod_1.z.object({ rule: zod_1.z.literal("immediate") }),
63
+ zod_1.z.object({
64
+ rule: zod_1.z.literal("send_at_local"),
65
+ time: zod_1.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "expected HH:mm"),
66
+ base: zod_1.z.enum(["target_date", "run_date"]),
67
+ }),
68
+ ]);
69
+ exports.zAutomationAutoTaskOutputSchema = zod_1.z.object({
70
+ type: zod_1.z.literal("auto_task"),
71
+ handler: zod_schemas_1.zTaskAutoHandlerSchema,
72
+ kind: zod_1.z.string().min(1),
73
+ payload: zod_1.z.record(zod_1.z.unknown()).default({}),
74
+ execute_at: exports.zAutomationExecuteAtSchema,
75
+ retry: zod_schemas_1.zTaskRetryPolicySchema.optional(),
76
+ on_failure: zod_schemas_1.zTaskOnFailureSchema.optional(),
77
+ });
78
+ exports.zAutomationHumanTaskOutputSchema = zod_1.z.object({
79
+ type: zod_1.z.literal("human_task"),
80
+ title: zod_1.z.string().min(1),
81
+ description: zod_1.z.string().optional(),
82
+ assignee_ref: zod_1.z.string().optional(),
83
+ });
84
+ exports.zAutomationOutputSchema = zod_1.z.discriminatedUnion("type", [
85
+ exports.zAutomationAutoTaskOutputSchema,
86
+ exports.zAutomationHumanTaskOutputSchema,
87
+ ]);
88
+ // ------------------------------------------------------
89
+ // Branches
90
+ // ------------------------------------------------------
91
+ exports.zAutomationBranchSchema = zod_1.z.object({
92
+ id: zod_1.z.string().min(1),
93
+ name: zod_1.z.string().min(1),
94
+ when: exports.zAutomationConditionGroupSchema.optional(),
95
+ is_fallback: zod_1.z.boolean().optional(),
96
+ outputs: zod_1.z.array(exports.zAutomationOutputSchema),
97
+ });
98
+ exports.zAutomationBranchModeSchema = zod_1.z.enum(["all", "exclusive"]);
99
+ // ------------------------------------------------------
100
+ // Routine
101
+ // ------------------------------------------------------
102
+ exports.zAutomationRoutineSchema = zod_1.z.object({
103
+ id: zod_1.z.string(),
104
+ name: zod_1.z.string().min(1),
105
+ description: zod_1.z.string().optional(),
106
+ active: zod_1.z.boolean().default(false),
107
+ version: zod_1.z.number().int().default(1),
108
+ trigger: exports.zAutomationTriggerSchema,
109
+ selection: exports.zAutomationSelectionSchema,
110
+ branch_mode: exports.zAutomationBranchModeSchema,
111
+ branches: zod_1.z.array(exports.zAutomationBranchSchema),
112
+ guards: zod_1.z.object({
113
+ max_tasks_per_run: zod_1.z.number().int().positive(),
114
+ }),
115
+ dry_run_stamp: zod_1.z
116
+ .object({
117
+ version: zod_1.z.number().int(),
118
+ at: zod_1.z.coerce.date(),
119
+ by: zod_1.z.string(),
120
+ })
121
+ .optional(),
122
+ trigger_state: zod_1.z
123
+ .object({
124
+ last_fired_at: zod_1.z.coerce.date().optional(),
125
+ })
126
+ .optional(),
127
+ stats: zod_1.z
128
+ .object({
129
+ last_run_at: zod_1.z.coerce.date().optional(),
130
+ last_materialized_at: zod_1.z.coerce.date().optional(),
131
+ last_run_id: zod_1.z.string().optional(),
132
+ })
133
+ .optional(),
134
+ created_at: zod_1.z.coerce.date(),
135
+ updated_at: zod_1.z.coerce.date(),
136
+ });
137
+ // ------------------------------------------------------
138
+ // Module config (mirrors zTaskRunnerConfigSchema: active default false, passthrough)
139
+ // ------------------------------------------------------
140
+ exports.zHubAutomationConfigSchema = zod_1.z
141
+ .object({
142
+ active: zod_1.z.boolean().default(false),
143
+ limits: zod_1.z
144
+ .object({
145
+ max_tasks_per_run_default: zod_1.z.number().int().optional(),
146
+ })
147
+ .passthrough()
148
+ .optional(),
149
+ })
150
+ .passthrough();
151
+ // ------------------------------------------------------
152
+ // Dry-run request (endpoint POST /routines/:id/dry-run)
153
+ // ------------------------------------------------------
154
+ exports.zAutomationDryRunRequestSchema = zod_1.z.object({
155
+ run_date: zod_1.z
156
+ .string()
157
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "expected yyyy-MM-dd")
158
+ .optional(),
159
+ });
@@ -0,0 +1,191 @@
1
+ import { z } from "zod";
2
+ import {
3
+ zTaskAutoHandlerSchema,
4
+ zTaskRetryPolicySchema,
5
+ zTaskOnFailureSchema,
6
+ } from "../evo-task/zod-schemas";
7
+
8
+ // ------------------------------------------------------
9
+ // Trigger (F1: cron only)
10
+ // ------------------------------------------------------
11
+ export const zAutomationCronTriggerSchema = z.object({
12
+ type: z.literal("cron"),
13
+ cron: z.object({
14
+ expression: z.string().min(1),
15
+ timezone: z.string().optional(),
16
+ }),
17
+ });
18
+
19
+ export const zAutomationTriggerSchema = zAutomationCronTriggerSchema;
20
+
21
+ // ------------------------------------------------------
22
+ // Selection (F1: appointment target only)
23
+ // ------------------------------------------------------
24
+ export const zAutomationDateOffsetModeSchema = z.enum(["calendar", "business"]);
25
+
26
+ export const zAutomationDateWindowSchema = z.object({
27
+ offset_days: z.number().int(), // may be negative (retroactive routines)
28
+ offset_mode: zAutomationDateOffsetModeSchema,
29
+ });
30
+
31
+ export const zAutomationAppointmentSelectionSchema = z.object({
32
+ target: z.literal("appointment"),
33
+ appointment: z.object({
34
+ calendar_ids: z.array(z.string()).optional(),
35
+ date_window: zAutomationDateWindowSchema,
36
+ status_in: z.array(z.string()).optional(),
37
+ status_base_in: z.array(z.string()).optional(),
38
+ appointment_type_not_in: z.array(z.string()).optional(),
39
+ }),
40
+ });
41
+
42
+ export const zAutomationSelectionSchema = zAutomationAppointmentSelectionSchema;
43
+
44
+ // ------------------------------------------------------
45
+ // Conditions (recursive AND/OR groups via z.lazy)
46
+ // ------------------------------------------------------
47
+ export const zAutomationOperatorSchema = z.enum([
48
+ "eq",
49
+ "neq",
50
+ "in",
51
+ "not_in",
52
+ "exists",
53
+ "not_exists",
54
+ "is_true",
55
+ "is_false",
56
+ ]);
57
+
58
+ export const zAutomationConditionSchema = z.object({
59
+ fact: z.string().min(1),
60
+ operator: zAutomationOperatorSchema,
61
+ value: z.unknown().optional(),
62
+ });
63
+
64
+ // z.lazy needs an explicit type annotation for the recursive reference.
65
+ type ZAutomationConditionGroup = {
66
+ combinator: "and" | "or";
67
+ conditions: Array<
68
+ z.infer<typeof zAutomationConditionSchema> | ZAutomationConditionGroup
69
+ >;
70
+ };
71
+
72
+ export const zAutomationConditionGroupSchema: z.ZodType<ZAutomationConditionGroup> =
73
+ z.lazy(() =>
74
+ z.object({
75
+ combinator: z.enum(["and", "or"]),
76
+ conditions: z.array(
77
+ z.union([zAutomationConditionSchema, zAutomationConditionGroupSchema])
78
+ ),
79
+ })
80
+ );
81
+
82
+ // ------------------------------------------------------
83
+ // Outputs (auto Task | human Task)
84
+ // ------------------------------------------------------
85
+ export const zAutomationExecuteAtSchema = z.discriminatedUnion("rule", [
86
+ z.object({ rule: z.literal("immediate") }),
87
+ z.object({
88
+ rule: z.literal("send_at_local"),
89
+ time: z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "expected HH:mm"),
90
+ base: z.enum(["target_date", "run_date"]),
91
+ }),
92
+ ]);
93
+
94
+ export const zAutomationAutoTaskOutputSchema = z.object({
95
+ type: z.literal("auto_task"),
96
+ handler: zTaskAutoHandlerSchema,
97
+ kind: z.string().min(1),
98
+ payload: z.record(z.unknown()).default({}),
99
+ execute_at: zAutomationExecuteAtSchema,
100
+ retry: zTaskRetryPolicySchema.optional(),
101
+ on_failure: zTaskOnFailureSchema.optional(),
102
+ });
103
+
104
+ export const zAutomationHumanTaskOutputSchema = z.object({
105
+ type: z.literal("human_task"),
106
+ title: z.string().min(1),
107
+ description: z.string().optional(),
108
+ assignee_ref: z.string().optional(),
109
+ });
110
+
111
+ export const zAutomationOutputSchema = z.discriminatedUnion("type", [
112
+ zAutomationAutoTaskOutputSchema,
113
+ zAutomationHumanTaskOutputSchema,
114
+ ]);
115
+
116
+ // ------------------------------------------------------
117
+ // Branches
118
+ // ------------------------------------------------------
119
+ export const zAutomationBranchSchema = z.object({
120
+ id: z.string().min(1),
121
+ name: z.string().min(1),
122
+ when: zAutomationConditionGroupSchema.optional(),
123
+ is_fallback: z.boolean().optional(),
124
+ outputs: z.array(zAutomationOutputSchema),
125
+ });
126
+
127
+ export const zAutomationBranchModeSchema = z.enum(["all", "exclusive"]);
128
+
129
+ // ------------------------------------------------------
130
+ // Routine
131
+ // ------------------------------------------------------
132
+ export const zAutomationRoutineSchema = z.object({
133
+ id: z.string(),
134
+ name: z.string().min(1),
135
+ description: z.string().optional(),
136
+ active: z.boolean().default(false),
137
+ version: z.number().int().default(1),
138
+ trigger: zAutomationTriggerSchema,
139
+ selection: zAutomationSelectionSchema,
140
+ branch_mode: zAutomationBranchModeSchema,
141
+ branches: z.array(zAutomationBranchSchema),
142
+ guards: z.object({
143
+ max_tasks_per_run: z.number().int().positive(),
144
+ }),
145
+ dry_run_stamp: z
146
+ .object({
147
+ version: z.number().int(),
148
+ at: z.coerce.date(),
149
+ by: z.string(),
150
+ })
151
+ .optional(),
152
+ trigger_state: z
153
+ .object({
154
+ last_fired_at: z.coerce.date().optional(),
155
+ })
156
+ .optional(),
157
+ stats: z
158
+ .object({
159
+ last_run_at: z.coerce.date().optional(),
160
+ last_materialized_at: z.coerce.date().optional(),
161
+ last_run_id: z.string().optional(),
162
+ })
163
+ .optional(),
164
+ created_at: z.coerce.date(),
165
+ updated_at: z.coerce.date(),
166
+ });
167
+
168
+ // ------------------------------------------------------
169
+ // Module config (mirrors zTaskRunnerConfigSchema: active default false, passthrough)
170
+ // ------------------------------------------------------
171
+ export const zHubAutomationConfigSchema = z
172
+ .object({
173
+ active: z.boolean().default(false),
174
+ limits: z
175
+ .object({
176
+ max_tasks_per_run_default: z.number().int().optional(),
177
+ })
178
+ .passthrough()
179
+ .optional(),
180
+ })
181
+ .passthrough();
182
+
183
+ // ------------------------------------------------------
184
+ // Dry-run request (endpoint POST /routines/:id/dry-run)
185
+ // ------------------------------------------------------
186
+ export const zAutomationDryRunRequestSchema = z.object({
187
+ run_date: z
188
+ .string()
189
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "expected yyyy-MM-dd")
190
+ .optional(),
191
+ });
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@ export * from "./types/evo-finops";
23
23
  export * from "./types/evo-notif-user";
24
24
  export * from "./types/evo-notifications";
25
25
  export * from "./types/evo-task-runner";
26
+ export * from "./types/hub-automation";
26
27
  export * from "./types/evo-integrations";
27
28
  export * from "./types/nex-customers";
28
29
  export * from "./types/nex-tenants";
@@ -66,4 +67,5 @@ export * from "./apps/evo-notif-user/zod-schemas";
66
67
  export * from "./apps/evo-notifications/zod-schemas";
67
68
  export * from "./apps/evo-notifications/quick-reply-action/zod-schemas";
68
69
  export * from "./apps/evo-task-runner/zod-schemas";
70
+ export * from "./apps/hub-automation/zod-schemas";
69
71
  export * from "./apps/evo-integrations/zod-schemas";
package/dist/index.js CHANGED
@@ -40,6 +40,7 @@ __exportStar(require("./types/evo-finops"), exports);
40
40
  __exportStar(require("./types/evo-notif-user"), exports);
41
41
  __exportStar(require("./types/evo-notifications"), exports);
42
42
  __exportStar(require("./types/evo-task-runner"), exports);
43
+ __exportStar(require("./types/hub-automation"), exports);
43
44
  __exportStar(require("./types/evo-integrations"), exports);
44
45
  __exportStar(require("./types/nex-customers"), exports);
45
46
  __exportStar(require("./types/nex-tenants"), exports);
@@ -84,4 +85,5 @@ __exportStar(require("./apps/evo-notif-user/zod-schemas"), exports);
84
85
  __exportStar(require("./apps/evo-notifications/zod-schemas"), exports);
85
86
  __exportStar(require("./apps/evo-notifications/quick-reply-action/zod-schemas"), exports);
86
87
  __exportStar(require("./apps/evo-task-runner/zod-schemas"), exports);
88
+ __exportStar(require("./apps/hub-automation/zod-schemas"), exports);
87
89
  __exportStar(require("./apps/evo-integrations/zod-schemas"), exports);
package/dist/index.ts CHANGED
@@ -24,6 +24,7 @@ export * from "./types/evo-finops";
24
24
  export * from "./types/evo-notif-user";
25
25
  export * from "./types/evo-notifications";
26
26
  export * from "./types/evo-task-runner";
27
+ export * from "./types/hub-automation";
27
28
  export * from "./types/evo-integrations";
28
29
  export * from "./types/nex-customers";
29
30
  export * from "./types/nex-tenants";
@@ -69,4 +70,5 @@ export * from "./apps/evo-notif-user/zod-schemas";
69
70
  export * from "./apps/evo-notifications/zod-schemas";
70
71
  export * from "./apps/evo-notifications/quick-reply-action/zod-schemas";
71
72
  export * from "./apps/evo-task-runner/zod-schemas";
73
+ export * from "./apps/hub-automation/zod-schemas";
72
74
  export * from "./apps/evo-integrations/zod-schemas";
@@ -46,6 +46,13 @@ export interface IIntegrationsAdapterDoc extends IFireDoc {
46
46
  * Precedência: calendar.integration.workflow_overrides → este doc → adapter code default.
47
47
  */
48
48
  default_workflow_urls: Partial<Record<CapabilityName, string>>;
49
+ /**
50
+ * Config de janelas default do adapter — largura/cadência que valem pra
51
+ * qualquer calendar que não sobrescreva.
52
+ * Precedência: calendar.integration.sync_config → este doc → default do código.
53
+ * Merge é campo-a-campo (ver ISyncWindowConfig), não substituição de bloco.
54
+ */
55
+ default_sync_config?: ISyncConfig | null;
49
56
  supported_capabilities: readonly CapabilityName[];
50
57
  auth_schema_version?: number;
51
58
  }
@@ -74,9 +81,32 @@ export interface ISyncedHashes {
74
81
  }
75
82
  export interface ISyncState extends IFireDoc {
76
83
  calendar_id: string;
84
+ /**
85
+ * Escalar: última run de QUALQUER janela. Não distingue qual janela rodou,
86
+ * então um `cold` de 5 min atrás faz o `hot` parecer fresco. Use
87
+ * `last_run_by_window` pra decidir cadência/frescor por janela.
88
+ */
77
89
  last_sync_at?: Date | null;
78
90
  last_window_type?: SyncWindowType;
91
+ /**
92
+ * Timestamp da última run POR janela. Sucessor de `last_sync_at` pra
93
+ * qualquer decisão de cadência ou de freshness gate.
94
+ */
95
+ last_run_by_window?: Partial<Record<SyncWindowType, Date>>;
96
+ /**
97
+ * Sobrescrito INTEIRO a cada run (o engine grava o snapshot da janela que
98
+ * acabou de rodar). Janelas disjuntas — ex.: `hot` -7/+14 vs
99
+ * `recent_reconcile` -30/-8 — destroem o cache uma da outra, e a run seguinte
100
+ * re-processa 100% da janela. Sucedido por `hashes_by_bucket`; mantido por
101
+ * compat durante a migração.
102
+ */
79
103
  last_synced_hashes: ISyncedHashes;
104
+ /**
105
+ * Hashes particionados por bucket, pra que cada janela preserve o próprio
106
+ * cache. Chave do bucket = window_type (ex.: `hot`) ou, em janelas longas
107
+ * chunkadas, o chunk (ex.: `warm:2026-08`).
108
+ */
109
+ hashes_by_bucket?: Record<string, ISyncedHashes>;
80
110
  last_coveredWindow?: ICoveredWindow | null;
81
111
  }
82
112
  export type SyncRunStatus = "success" | "partial" | "error";
@@ -106,12 +136,23 @@ export interface ISyncRunEvent {
106
136
  n8n_calls: number;
107
137
  errors?: ISyncRunEventError[];
108
138
  }
139
+ /**
140
+ * Todos os campos são opcionais: a config resolvida é um merge campo-a-campo de
141
+ * calendar.integration.sync_config → adapter.default_sync_config → default do
142
+ * código. Um calendar que só quer ajustar `window_days` omite o resto e herda.
143
+ *
144
+ * `window_days` é indivisível de propósito: `past` sem `future` não descreve
145
+ * janela nenhuma, e o resolver (`buildRequestedWindow`) consome o par.
146
+ */
109
147
  export interface ISyncWindowConfig {
110
- enabled: boolean;
148
+ enabled?: boolean;
111
149
  /** Cadência em minutos. Ex.: hot=60, warm=360, cold=10080 (semanal). */
112
- cadence_minutes: number;
113
- /** Janela absoluta em dias a partir de "hoje". */
114
- window_days: {
150
+ cadence_minutes?: number;
151
+ /**
152
+ * Janela absoluta em dias a partir de "hoje". `future` pode ser negativo —
153
+ * janela que termina no passado (ex.: recent_reconcile: past=30, future=-8).
154
+ */
155
+ window_days?: {
115
156
  past: number;
116
157
  future: number;
117
158
  };
@@ -114,6 +114,13 @@ export interface IIntegrationsAdapterDoc extends IFireDoc {
114
114
  * Precedência: calendar.integration.workflow_overrides → este doc → adapter code default.
115
115
  */
116
116
  default_workflow_urls: Partial<Record<CapabilityName, string>>;
117
+ /**
118
+ * Config de janelas default do adapter — largura/cadência que valem pra
119
+ * qualquer calendar que não sobrescreva.
120
+ * Precedência: calendar.integration.sync_config → este doc → default do código.
121
+ * Merge é campo-a-campo (ver ISyncWindowConfig), não substituição de bloco.
122
+ */
123
+ default_sync_config?: ISyncConfig | null;
117
124
  supported_capabilities: readonly CapabilityName[];
118
125
  auth_schema_version?: number;
119
126
  }
@@ -158,9 +165,32 @@ export interface ISyncedHashes {
158
165
 
159
166
  export interface ISyncState extends IFireDoc {
160
167
  calendar_id: string;
168
+ /**
169
+ * Escalar: última run de QUALQUER janela. Não distingue qual janela rodou,
170
+ * então um `cold` de 5 min atrás faz o `hot` parecer fresco. Use
171
+ * `last_run_by_window` pra decidir cadência/frescor por janela.
172
+ */
161
173
  last_sync_at?: Date | null;
162
174
  last_window_type?: SyncWindowType;
175
+ /**
176
+ * Timestamp da última run POR janela. Sucessor de `last_sync_at` pra
177
+ * qualquer decisão de cadência ou de freshness gate.
178
+ */
179
+ last_run_by_window?: Partial<Record<SyncWindowType, Date>>;
180
+ /**
181
+ * Sobrescrito INTEIRO a cada run (o engine grava o snapshot da janela que
182
+ * acabou de rodar). Janelas disjuntas — ex.: `hot` -7/+14 vs
183
+ * `recent_reconcile` -30/-8 — destroem o cache uma da outra, e a run seguinte
184
+ * re-processa 100% da janela. Sucedido por `hashes_by_bucket`; mantido por
185
+ * compat durante a migração.
186
+ */
163
187
  last_synced_hashes: ISyncedHashes;
188
+ /**
189
+ * Hashes particionados por bucket, pra que cada janela preserve o próprio
190
+ * cache. Chave do bucket = window_type (ex.: `hot`) ou, em janelas longas
191
+ * chunkadas, o chunk (ex.: `warm:2026-08`).
192
+ */
193
+ hashes_by_bucket?: Record<string, ISyncedHashes>;
164
194
  last_coveredWindow?: ICoveredWindow | null;
165
195
  }
166
196
 
@@ -204,12 +234,23 @@ export interface ISyncRunEvent {
204
234
  // Ver IMedCalendar em evo-types/src/types/evo-med/calendar.
205
235
  // ======================================================
206
236
 
237
+ /**
238
+ * Todos os campos são opcionais: a config resolvida é um merge campo-a-campo de
239
+ * calendar.integration.sync_config → adapter.default_sync_config → default do
240
+ * código. Um calendar que só quer ajustar `window_days` omite o resto e herda.
241
+ *
242
+ * `window_days` é indivisível de propósito: `past` sem `future` não descreve
243
+ * janela nenhuma, e o resolver (`buildRequestedWindow`) consome o par.
244
+ */
207
245
  export interface ISyncWindowConfig {
208
- enabled: boolean;
246
+ enabled?: boolean;
209
247
  /** Cadência em minutos. Ex.: hot=60, warm=360, cold=10080 (semanal). */
210
- cadence_minutes: number;
211
- /** Janela absoluta em dias a partir de "hoje". */
212
- window_days: {
248
+ cadence_minutes?: number;
249
+ /**
250
+ * Janela absoluta em dias a partir de "hoje". `future` pode ser negativo —
251
+ * janela que termina no passado (ex.: recent_reconcile: past=30, future=-8).
252
+ */
253
+ window_days?: {
213
254
  past: number;
214
255
  future: number;
215
256
  };
@@ -55,6 +55,7 @@ export declare const TaskAutoHandlerEnum: {
55
55
  readonly LeadReactivation: "lead_reactivation";
56
56
  readonly AppointmentAction: "appointment_action";
57
57
  readonly AppointmentReminder: "appointment_reminder";
58
+ readonly IntegrationsSyncRun: "evo-integrations.sync-run";
58
59
  };
59
60
  export type TaskAutoHandler = (typeof TaskAutoHandlerEnum)[keyof typeof TaskAutoHandlerEnum];
60
61
  export declare const TaskRetryStrategyEnum: {
@@ -98,6 +98,13 @@ exports.TaskAutoHandlerEnum = {
98
98
  // por canal habilitado (WhatsApp/e-mail), com quick-reply de confirmar/remarcar.
99
99
  // Tópico PubSub do executor: `appointment_reminder.execute_requests`.
100
100
  AppointmentReminder: "appointment_reminder",
101
+ // feat-078: handler que roda um sync de agenda do evo-integrations. O valor
102
+ // é o nome do handler COM ponto de propósito — `resolveHandlerTopic` faz
103
+ // `${handler}.execute_requests`, e a CF `integrations_sync` já escuta
104
+ // `evo-integrations.sync-run.execute_requests` (= SYNC_RUN_HANDLER em
105
+ // types/evo-integrations). Permite que o `/force` roteie pelo task-runner e
106
+ // herde retry/backoff/DLQ, em vez de montar a mensagem PubSub na mão.
107
+ IntegrationsSyncRun: "evo-integrations.sync-run",
101
108
  };
102
109
  // ----- Retry policy
103
110
  exports.TaskRetryStrategyEnum = {
@@ -109,6 +109,13 @@ export const TaskAutoHandlerEnum = {
109
109
  // por canal habilitado (WhatsApp/e-mail), com quick-reply de confirmar/remarcar.
110
110
  // Tópico PubSub do executor: `appointment_reminder.execute_requests`.
111
111
  AppointmentReminder: "appointment_reminder",
112
+ // feat-078: handler que roda um sync de agenda do evo-integrations. O valor
113
+ // é o nome do handler COM ponto de propósito — `resolveHandlerTopic` faz
114
+ // `${handler}.execute_requests`, e a CF `integrations_sync` já escuta
115
+ // `evo-integrations.sync-run.execute_requests` (= SYNC_RUN_HANDLER em
116
+ // types/evo-integrations). Permite que o `/force` roteie pelo task-runner e
117
+ // herde retry/backoff/DLQ, em vez de montar a mensagem PubSub na mão.
118
+ IntegrationsSyncRun: "evo-integrations.sync-run",
112
119
  } as const;
113
120
 
114
121
  export type TaskAutoHandler =
@@ -0,0 +1,4 @@
1
+ export declare const HUB_AUTOMATION_APP = "hub-automation";
2
+ export declare const ROUTINES_COLLECTION = "routines";
3
+ export declare const RUNS_COLLECTION = "runs";
4
+ export declare const HUB_AUTOMATION_CONFIG_DOC = "config";
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ // Firestore collection/doc identifiers for the hub-automation module.
3
+ // Base path: tenants/{tenant}/apps/hub-automation/...
4
+ // - `config` subcollection reuses the shared CONFIG_COLLECTION ("config")
5
+ // - HUB_AUTOMATION_CONFIG_DOC is the fixed doc id inside that subcollection
6
+ // (path: tenants/{tenant}/apps/hub-automation/config/config)
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.HUB_AUTOMATION_CONFIG_DOC = exports.RUNS_COLLECTION = exports.ROUTINES_COLLECTION = exports.HUB_AUTOMATION_APP = void 0;
9
+ // ----- App identifier (Firestore path: tenants/{t}/apps/hub-automation/...)
10
+ exports.HUB_AUTOMATION_APP = "hub-automation";
11
+ // ----- Routines collection: tenants/{t}/apps/hub-automation/routines/{routineId}
12
+ exports.ROUTINES_COLLECTION = "routines";
13
+ // ----- Run traces collection: tenants/{t}/apps/hub-automation/runs/{runId}
14
+ exports.RUNS_COLLECTION = "runs";
15
+ // ----- Fixed config doc id inside the shared `config` subcollection
16
+ exports.HUB_AUTOMATION_CONFIG_DOC = "config";
@@ -0,0 +1,17 @@
1
+ // Firestore collection/doc identifiers for the hub-automation module.
2
+ // Base path: tenants/{tenant}/apps/hub-automation/...
3
+ // - `config` subcollection reuses the shared CONFIG_COLLECTION ("config")
4
+ // - HUB_AUTOMATION_CONFIG_DOC is the fixed doc id inside that subcollection
5
+ // (path: tenants/{tenant}/apps/hub-automation/config/config)
6
+
7
+ // ----- App identifier (Firestore path: tenants/{t}/apps/hub-automation/...)
8
+ export const HUB_AUTOMATION_APP = "hub-automation";
9
+
10
+ // ----- Routines collection: tenants/{t}/apps/hub-automation/routines/{routineId}
11
+ export const ROUTINES_COLLECTION = "routines";
12
+
13
+ // ----- Run traces collection: tenants/{t}/apps/hub-automation/runs/{runId}
14
+ export const RUNS_COLLECTION = "runs";
15
+
16
+ // ----- Fixed config doc id inside the shared `config` subcollection
17
+ export const HUB_AUTOMATION_CONFIG_DOC = "config";