@qcobro/common 1.12.4 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/engineEval.d.ts +67 -0
- package/dist/bin/engineEval.d.ts.map +1 -0
- package/dist/bin/engineEval.js +290 -0
- package/dist/bin/engineEval.js.map +1 -0
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -2
- package/dist/config.js.map +1 -1
- package/dist/evaluation/evaluate.d.ts +4 -0
- package/dist/evaluation/evaluate.d.ts.map +1 -0
- package/dist/evaluation/evaluate.js +504 -0
- package/dist/evaluation/evaluate.js.map +1 -0
- package/dist/evaluation/index.d.ts +3 -0
- package/dist/evaluation/index.d.ts.map +1 -0
- package/dist/evaluation/index.js +3 -0
- package/dist/evaluation/index.js.map +1 -0
- package/dist/evaluation/scorecard.d.ts +84 -0
- package/dist/evaluation/scorecard.d.ts.map +1 -0
- package/dist/evaluation/scorecard.js +29 -0
- package/dist/evaluation/scorecard.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/schemas/engineEvents.d.ts +407 -0
- package/dist/schemas/engineEvents.d.ts.map +1 -0
- package/dist/schemas/engineEvents.js +179 -0
- package/dist/schemas/engineEvents.js.map +1 -0
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/index.js.map +1 -1
- package/dist/types/engine.d.ts +5 -0
- package/dist/types/engine.d.ts.map +1 -1
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/pacing.d.ts +17 -0
- package/dist/utils/pacing.d.ts.map +1 -0
- package/dist/utils/pacing.js +18 -0
- package/dist/utils/pacing.js.map +1 -0
- package/dist/utils/time.d.ts +16 -0
- package/dist/utils/time.d.ts.map +1 -1
- package/dist/utils/time.js +17 -0
- package/dist/utils/time.js.map +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Contracts for the engine judge: the parameter set `evaluate` runs against and
|
|
4
|
+
* the scorecard it produces. Thresholds default here; rate caps and the tick
|
|
5
|
+
* interval mirror the deployment's engine config and are supplied by the caller
|
|
6
|
+
* (the events endpoint returns them alongside the stream).
|
|
7
|
+
*/
|
|
8
|
+
export const evaluationParametersSchema = z.object({
|
|
9
|
+
/** Seconds between engine ticks (`engine.tickSeconds`). */
|
|
10
|
+
tickSeconds: z.number().int().positive(),
|
|
11
|
+
/** Deployment-wide pacing caps, mirroring the engine config. `0` = channel paused. */
|
|
12
|
+
ratesPerMinute: z.object({
|
|
13
|
+
voice: z.number().nonnegative(),
|
|
14
|
+
sms: z.number().nonnegative(),
|
|
15
|
+
email: z.number().nonnegative(),
|
|
16
|
+
whatsApp: z.number().nonnegative()
|
|
17
|
+
}),
|
|
18
|
+
thresholds: z
|
|
19
|
+
.object({
|
|
20
|
+
/** PERF-2: p95 of provider dispatch latency (the API call, not call duration). */
|
|
21
|
+
dispatchLatencyP95Ms: z.number().positive().default(2000),
|
|
22
|
+
/** PERF-3: max fraction of dispatches that may fail, per channel. */
|
|
23
|
+
maxErrorRate: z.number().min(0).max(1).default(0.02),
|
|
24
|
+
/** LIVE-1: max consecutive budget-starved in-window ticks before an account counts as starved. */
|
|
25
|
+
livenessTicks: z.number().int().positive().default(10)
|
|
26
|
+
})
|
|
27
|
+
.prefault({})
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=scorecard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorecard.js","sourceRoot":"","sources":["../../src/evaluation/scorecard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,2DAA2D;IAC3D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACxC,sFAAsF;IACtF,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;QAC/B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;QAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;KACnC,CAAC;IACF,UAAU,EAAE,CAAC;SACV,MAAM,CAAC;QACN,kFAAkF;QAClF,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QACzD,qEAAqE;QACrE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QACpD,kGAAkG;QAClG,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KACvD,CAAC;SACD,QAAQ,CAAC,EAAE,CAAC;CAChB,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./errors/index.js";
|
|
|
3
3
|
export * from "./utils/index.js";
|
|
4
4
|
export * from "./schemas/index.js";
|
|
5
5
|
export * from "./types/index.js";
|
|
6
|
+
export * from "./evaluation/index.js";
|
|
6
7
|
export * from "./config.js";
|
|
7
8
|
/**
|
|
8
9
|
* Placeholder contract proving the shared-schema pattern.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS;;iBAEpB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS;;iBAEpB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./errors/index.js";
|
|
|
3
3
|
export * from "./utils/index.js";
|
|
4
4
|
export * from "./schemas/index.js";
|
|
5
5
|
export * from "./types/index.js";
|
|
6
|
+
export * from "./evaluation/index.js";
|
|
6
7
|
export * from "./config.js";
|
|
7
8
|
/**
|
|
8
9
|
* Placeholder contract proving the shared-schema pattern.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CACpC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CACpC,CAAC,CAAC"}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Engine flight-recorder events. The engine (and the inbound provider webhooks)
|
|
4
|
+
* emit these as an append-only stream; the pure evaluator in `../evaluation/`
|
|
5
|
+
* replays a stream to prove a run stayed within parameters. Events are
|
|
6
|
+
* self-contained: `campaign.evaluated` snapshots the config in force that tick,
|
|
7
|
+
* so evaluating never requires reading live campaign rows.
|
|
8
|
+
*
|
|
9
|
+
* Correlation spine: `tickId` + `seq` order events within a tick;
|
|
10
|
+
* `workspaceRef`/`campaignId`/`portfolioAccountId`/`providerRef` tie them to the
|
|
11
|
+
* domain. Only tick lifecycle events are deployment-level (one engine loop ticks
|
|
12
|
+
* across all workspaces) — everything else carries `workspaceRef`.
|
|
13
|
+
*
|
|
14
|
+
* Privacy: recipient identifiers are masked (see `maskRecipient`); rendered
|
|
15
|
+
* bodies, scripts, and transcripts never enter the stream (they live on the
|
|
16
|
+
* gestión).
|
|
17
|
+
*/
|
|
18
|
+
export declare const engineEventKindSchema: z.ZodEnum<{
|
|
19
|
+
"tick.started": "tick.started";
|
|
20
|
+
"tick.completed": "tick.completed";
|
|
21
|
+
"campaign.evaluated": "campaign.evaluated";
|
|
22
|
+
"account.decided": "account.decided";
|
|
23
|
+
"attempt.reserved": "attempt.reserved";
|
|
24
|
+
"dispatch.requested": "dispatch.requested";
|
|
25
|
+
"dispatch.succeeded": "dispatch.succeeded";
|
|
26
|
+
"dispatch.failed": "dispatch.failed";
|
|
27
|
+
"provider.event": "provider.event";
|
|
28
|
+
}>;
|
|
29
|
+
export type EngineEventKind = z.infer<typeof engineEventKindSchema>;
|
|
30
|
+
/** Snapshot of the campaign parameters in force during a tick (self-contained stream). */
|
|
31
|
+
export declare const campaignSnapshotSchema: z.ZodObject<{
|
|
32
|
+
status: z.ZodString;
|
|
33
|
+
startDate: z.ZodString;
|
|
34
|
+
endDate: z.ZodNullable<z.ZodString>;
|
|
35
|
+
daysOfWeek: z.ZodArray<z.ZodNumber>;
|
|
36
|
+
startTime: z.ZodString;
|
|
37
|
+
endTime: z.ZodString;
|
|
38
|
+
maxAttemptsPerAccount: z.ZodNumber;
|
|
39
|
+
maxAttemptsPerDay: z.ZodNumber;
|
|
40
|
+
timezone: z.ZodString;
|
|
41
|
+
channel: z.ZodNullable<z.ZodEnum<{
|
|
42
|
+
VOICE_AI: "VOICE_AI";
|
|
43
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
44
|
+
SMS: "SMS";
|
|
45
|
+
EMAIL: "EMAIL";
|
|
46
|
+
WHATSAPP: "WHATSAPP";
|
|
47
|
+
}>>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export type CampaignSnapshot = z.infer<typeof campaignSnapshotSchema>;
|
|
50
|
+
declare const tickStartedSchema: z.ZodObject<{
|
|
51
|
+
id: z.ZodString;
|
|
52
|
+
at: z.ZodString;
|
|
53
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
54
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
kind: z.ZodLiteral<"tick.started">;
|
|
56
|
+
budgets: z.ZodRecord<z.ZodEnum<{
|
|
57
|
+
VOICE_AI: "VOICE_AI";
|
|
58
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
59
|
+
SMS: "SMS";
|
|
60
|
+
EMAIL: "EMAIL";
|
|
61
|
+
WHATSAPP: "WHATSAPP";
|
|
62
|
+
}> & z.core.$partial, z.ZodNumber>;
|
|
63
|
+
perTickMax: z.ZodOptional<z.ZodNumber>;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
declare const tickCompletedSchema: z.ZodObject<{
|
|
66
|
+
id: z.ZodString;
|
|
67
|
+
at: z.ZodString;
|
|
68
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
69
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
70
|
+
kind: z.ZodLiteral<"tick.completed">;
|
|
71
|
+
durationMs: z.ZodNumber;
|
|
72
|
+
dispatched: z.ZodNumber;
|
|
73
|
+
perTickMaxReached: z.ZodBoolean;
|
|
74
|
+
channelUsage: z.ZodRecord<z.ZodEnum<{
|
|
75
|
+
VOICE_AI: "VOICE_AI";
|
|
76
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
77
|
+
SMS: "SMS";
|
|
78
|
+
EMAIL: "EMAIL";
|
|
79
|
+
WHATSAPP: "WHATSAPP";
|
|
80
|
+
}> & z.core.$partial, z.ZodObject<{
|
|
81
|
+
dispatched: z.ZodNumber;
|
|
82
|
+
budget: z.ZodNumber;
|
|
83
|
+
}, z.core.$strip>>;
|
|
84
|
+
}, z.core.$strip>;
|
|
85
|
+
declare const campaignEvaluatedSchema: z.ZodObject<{
|
|
86
|
+
id: z.ZodString;
|
|
87
|
+
at: z.ZodString;
|
|
88
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
89
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
workspaceRef: z.ZodString;
|
|
91
|
+
kind: z.ZodLiteral<"campaign.evaluated">;
|
|
92
|
+
campaignId: z.ZodString;
|
|
93
|
+
campaignName: z.ZodOptional<z.ZodString>;
|
|
94
|
+
inWindow: z.ZodBoolean;
|
|
95
|
+
skipReason: z.ZodOptional<z.ZodString>;
|
|
96
|
+
completed: z.ZodOptional<z.ZodBoolean>;
|
|
97
|
+
candidateCount: z.ZodNumber;
|
|
98
|
+
snapshot: z.ZodObject<{
|
|
99
|
+
status: z.ZodString;
|
|
100
|
+
startDate: z.ZodString;
|
|
101
|
+
endDate: z.ZodNullable<z.ZodString>;
|
|
102
|
+
daysOfWeek: z.ZodArray<z.ZodNumber>;
|
|
103
|
+
startTime: z.ZodString;
|
|
104
|
+
endTime: z.ZodString;
|
|
105
|
+
maxAttemptsPerAccount: z.ZodNumber;
|
|
106
|
+
maxAttemptsPerDay: z.ZodNumber;
|
|
107
|
+
timezone: z.ZodString;
|
|
108
|
+
channel: z.ZodNullable<z.ZodEnum<{
|
|
109
|
+
VOICE_AI: "VOICE_AI";
|
|
110
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
111
|
+
SMS: "SMS";
|
|
112
|
+
EMAIL: "EMAIL";
|
|
113
|
+
WHATSAPP: "WHATSAPP";
|
|
114
|
+
}>>;
|
|
115
|
+
}, z.core.$strip>;
|
|
116
|
+
}, z.core.$strip>;
|
|
117
|
+
declare const accountDecidedSchema: z.ZodObject<{
|
|
118
|
+
id: z.ZodString;
|
|
119
|
+
at: z.ZodString;
|
|
120
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
121
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
122
|
+
workspaceRef: z.ZodString;
|
|
123
|
+
kind: z.ZodLiteral<"account.decided">;
|
|
124
|
+
campaignId: z.ZodString;
|
|
125
|
+
portfolioAccountId: z.ZodString;
|
|
126
|
+
decision: z.ZodString;
|
|
127
|
+
providerRef: z.ZodOptional<z.ZodString>;
|
|
128
|
+
}, z.core.$strip>;
|
|
129
|
+
declare const attemptReservedSchema: z.ZodObject<{
|
|
130
|
+
id: z.ZodString;
|
|
131
|
+
at: z.ZodString;
|
|
132
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
133
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
134
|
+
workspaceRef: z.ZodString;
|
|
135
|
+
kind: z.ZodLiteral<"attempt.reserved">;
|
|
136
|
+
campaignId: z.ZodString;
|
|
137
|
+
portfolioAccountId: z.ZodString;
|
|
138
|
+
}, z.core.$strip>;
|
|
139
|
+
declare const dispatchRequestedSchema: z.ZodObject<{
|
|
140
|
+
id: z.ZodString;
|
|
141
|
+
at: z.ZodString;
|
|
142
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
143
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
144
|
+
workspaceRef: z.ZodString;
|
|
145
|
+
kind: z.ZodLiteral<"dispatch.requested">;
|
|
146
|
+
campaignId: z.ZodString;
|
|
147
|
+
portfolioAccountId: z.ZodString;
|
|
148
|
+
channel: z.ZodEnum<{
|
|
149
|
+
VOICE_AI: "VOICE_AI";
|
|
150
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
151
|
+
SMS: "SMS";
|
|
152
|
+
EMAIL: "EMAIL";
|
|
153
|
+
WHATSAPP: "WHATSAPP";
|
|
154
|
+
}>;
|
|
155
|
+
toMasked: z.ZodString;
|
|
156
|
+
}, z.core.$strip>;
|
|
157
|
+
declare const dispatchSucceededSchema: z.ZodObject<{
|
|
158
|
+
id: z.ZodString;
|
|
159
|
+
at: z.ZodString;
|
|
160
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
161
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
162
|
+
workspaceRef: z.ZodString;
|
|
163
|
+
kind: z.ZodLiteral<"dispatch.succeeded">;
|
|
164
|
+
campaignId: z.ZodString;
|
|
165
|
+
portfolioAccountId: z.ZodString;
|
|
166
|
+
channel: z.ZodEnum<{
|
|
167
|
+
VOICE_AI: "VOICE_AI";
|
|
168
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
169
|
+
SMS: "SMS";
|
|
170
|
+
EMAIL: "EMAIL";
|
|
171
|
+
WHATSAPP: "WHATSAPP";
|
|
172
|
+
}>;
|
|
173
|
+
providerRef: z.ZodString;
|
|
174
|
+
latencyMs: z.ZodNumber;
|
|
175
|
+
toMasked: z.ZodString;
|
|
176
|
+
}, z.core.$strip>;
|
|
177
|
+
declare const dispatchFailedSchema: z.ZodObject<{
|
|
178
|
+
id: z.ZodString;
|
|
179
|
+
at: z.ZodString;
|
|
180
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
181
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
182
|
+
workspaceRef: z.ZodString;
|
|
183
|
+
kind: z.ZodLiteral<"dispatch.failed">;
|
|
184
|
+
campaignId: z.ZodString;
|
|
185
|
+
portfolioAccountId: z.ZodString;
|
|
186
|
+
channel: z.ZodEnum<{
|
|
187
|
+
VOICE_AI: "VOICE_AI";
|
|
188
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
189
|
+
SMS: "SMS";
|
|
190
|
+
EMAIL: "EMAIL";
|
|
191
|
+
WHATSAPP: "WHATSAPP";
|
|
192
|
+
}>;
|
|
193
|
+
latencyMs: z.ZodNumber;
|
|
194
|
+
errorClass: z.ZodString;
|
|
195
|
+
errorMessage: z.ZodString;
|
|
196
|
+
toMasked: z.ZodString;
|
|
197
|
+
}, z.core.$strip>;
|
|
198
|
+
declare const providerEventSchema: z.ZodObject<{
|
|
199
|
+
id: z.ZodString;
|
|
200
|
+
at: z.ZodString;
|
|
201
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
202
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
203
|
+
kind: z.ZodLiteral<"provider.event">;
|
|
204
|
+
workspaceRef: z.ZodOptional<z.ZodString>;
|
|
205
|
+
source: z.ZodEnum<{
|
|
206
|
+
"voice-events": "voice-events";
|
|
207
|
+
"contact-logs": "contact-logs";
|
|
208
|
+
"meta-whatsapp": "meta-whatsapp";
|
|
209
|
+
"email-inbound": "email-inbound";
|
|
210
|
+
}>;
|
|
211
|
+
providerRef: z.ZodOptional<z.ZodString>;
|
|
212
|
+
providerAt: z.ZodOptional<z.ZodString>;
|
|
213
|
+
matched: z.ZodBoolean;
|
|
214
|
+
campaignId: z.ZodOptional<z.ZodString>;
|
|
215
|
+
portfolioAccountId: z.ZodOptional<z.ZodString>;
|
|
216
|
+
summary: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
217
|
+
}, z.core.$strip>;
|
|
218
|
+
export declare const engineEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
219
|
+
id: z.ZodString;
|
|
220
|
+
at: z.ZodString;
|
|
221
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
222
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
223
|
+
kind: z.ZodLiteral<"tick.started">;
|
|
224
|
+
budgets: z.ZodRecord<z.ZodEnum<{
|
|
225
|
+
VOICE_AI: "VOICE_AI";
|
|
226
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
227
|
+
SMS: "SMS";
|
|
228
|
+
EMAIL: "EMAIL";
|
|
229
|
+
WHATSAPP: "WHATSAPP";
|
|
230
|
+
}> & z.core.$partial, z.ZodNumber>;
|
|
231
|
+
perTickMax: z.ZodOptional<z.ZodNumber>;
|
|
232
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
233
|
+
id: z.ZodString;
|
|
234
|
+
at: z.ZodString;
|
|
235
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
236
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
237
|
+
kind: z.ZodLiteral<"tick.completed">;
|
|
238
|
+
durationMs: z.ZodNumber;
|
|
239
|
+
dispatched: z.ZodNumber;
|
|
240
|
+
perTickMaxReached: z.ZodBoolean;
|
|
241
|
+
channelUsage: z.ZodRecord<z.ZodEnum<{
|
|
242
|
+
VOICE_AI: "VOICE_AI";
|
|
243
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
244
|
+
SMS: "SMS";
|
|
245
|
+
EMAIL: "EMAIL";
|
|
246
|
+
WHATSAPP: "WHATSAPP";
|
|
247
|
+
}> & z.core.$partial, z.ZodObject<{
|
|
248
|
+
dispatched: z.ZodNumber;
|
|
249
|
+
budget: z.ZodNumber;
|
|
250
|
+
}, z.core.$strip>>;
|
|
251
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
252
|
+
id: z.ZodString;
|
|
253
|
+
at: z.ZodString;
|
|
254
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
255
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
256
|
+
workspaceRef: z.ZodString;
|
|
257
|
+
kind: z.ZodLiteral<"campaign.evaluated">;
|
|
258
|
+
campaignId: z.ZodString;
|
|
259
|
+
campaignName: z.ZodOptional<z.ZodString>;
|
|
260
|
+
inWindow: z.ZodBoolean;
|
|
261
|
+
skipReason: z.ZodOptional<z.ZodString>;
|
|
262
|
+
completed: z.ZodOptional<z.ZodBoolean>;
|
|
263
|
+
candidateCount: z.ZodNumber;
|
|
264
|
+
snapshot: z.ZodObject<{
|
|
265
|
+
status: z.ZodString;
|
|
266
|
+
startDate: z.ZodString;
|
|
267
|
+
endDate: z.ZodNullable<z.ZodString>;
|
|
268
|
+
daysOfWeek: z.ZodArray<z.ZodNumber>;
|
|
269
|
+
startTime: z.ZodString;
|
|
270
|
+
endTime: z.ZodString;
|
|
271
|
+
maxAttemptsPerAccount: z.ZodNumber;
|
|
272
|
+
maxAttemptsPerDay: z.ZodNumber;
|
|
273
|
+
timezone: z.ZodString;
|
|
274
|
+
channel: z.ZodNullable<z.ZodEnum<{
|
|
275
|
+
VOICE_AI: "VOICE_AI";
|
|
276
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
277
|
+
SMS: "SMS";
|
|
278
|
+
EMAIL: "EMAIL";
|
|
279
|
+
WHATSAPP: "WHATSAPP";
|
|
280
|
+
}>>;
|
|
281
|
+
}, z.core.$strip>;
|
|
282
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
283
|
+
id: z.ZodString;
|
|
284
|
+
at: z.ZodString;
|
|
285
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
286
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
287
|
+
workspaceRef: z.ZodString;
|
|
288
|
+
kind: z.ZodLiteral<"account.decided">;
|
|
289
|
+
campaignId: z.ZodString;
|
|
290
|
+
portfolioAccountId: z.ZodString;
|
|
291
|
+
decision: z.ZodString;
|
|
292
|
+
providerRef: z.ZodOptional<z.ZodString>;
|
|
293
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
294
|
+
id: z.ZodString;
|
|
295
|
+
at: z.ZodString;
|
|
296
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
297
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
298
|
+
workspaceRef: z.ZodString;
|
|
299
|
+
kind: z.ZodLiteral<"attempt.reserved">;
|
|
300
|
+
campaignId: z.ZodString;
|
|
301
|
+
portfolioAccountId: z.ZodString;
|
|
302
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
303
|
+
id: z.ZodString;
|
|
304
|
+
at: z.ZodString;
|
|
305
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
306
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
307
|
+
workspaceRef: z.ZodString;
|
|
308
|
+
kind: z.ZodLiteral<"dispatch.requested">;
|
|
309
|
+
campaignId: z.ZodString;
|
|
310
|
+
portfolioAccountId: z.ZodString;
|
|
311
|
+
channel: z.ZodEnum<{
|
|
312
|
+
VOICE_AI: "VOICE_AI";
|
|
313
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
314
|
+
SMS: "SMS";
|
|
315
|
+
EMAIL: "EMAIL";
|
|
316
|
+
WHATSAPP: "WHATSAPP";
|
|
317
|
+
}>;
|
|
318
|
+
toMasked: z.ZodString;
|
|
319
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
320
|
+
id: z.ZodString;
|
|
321
|
+
at: z.ZodString;
|
|
322
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
323
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
324
|
+
workspaceRef: z.ZodString;
|
|
325
|
+
kind: z.ZodLiteral<"dispatch.succeeded">;
|
|
326
|
+
campaignId: z.ZodString;
|
|
327
|
+
portfolioAccountId: z.ZodString;
|
|
328
|
+
channel: z.ZodEnum<{
|
|
329
|
+
VOICE_AI: "VOICE_AI";
|
|
330
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
331
|
+
SMS: "SMS";
|
|
332
|
+
EMAIL: "EMAIL";
|
|
333
|
+
WHATSAPP: "WHATSAPP";
|
|
334
|
+
}>;
|
|
335
|
+
providerRef: z.ZodString;
|
|
336
|
+
latencyMs: z.ZodNumber;
|
|
337
|
+
toMasked: z.ZodString;
|
|
338
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
339
|
+
id: z.ZodString;
|
|
340
|
+
at: z.ZodString;
|
|
341
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
342
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
343
|
+
workspaceRef: z.ZodString;
|
|
344
|
+
kind: z.ZodLiteral<"dispatch.failed">;
|
|
345
|
+
campaignId: z.ZodString;
|
|
346
|
+
portfolioAccountId: z.ZodString;
|
|
347
|
+
channel: z.ZodEnum<{
|
|
348
|
+
VOICE_AI: "VOICE_AI";
|
|
349
|
+
VOICE_PRERECORDED: "VOICE_PRERECORDED";
|
|
350
|
+
SMS: "SMS";
|
|
351
|
+
EMAIL: "EMAIL";
|
|
352
|
+
WHATSAPP: "WHATSAPP";
|
|
353
|
+
}>;
|
|
354
|
+
latencyMs: z.ZodNumber;
|
|
355
|
+
errorClass: z.ZodString;
|
|
356
|
+
errorMessage: z.ZodString;
|
|
357
|
+
toMasked: z.ZodString;
|
|
358
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
359
|
+
id: z.ZodString;
|
|
360
|
+
at: z.ZodString;
|
|
361
|
+
tickId: z.ZodOptional<z.ZodString>;
|
|
362
|
+
seq: z.ZodOptional<z.ZodNumber>;
|
|
363
|
+
kind: z.ZodLiteral<"provider.event">;
|
|
364
|
+
workspaceRef: z.ZodOptional<z.ZodString>;
|
|
365
|
+
source: z.ZodEnum<{
|
|
366
|
+
"voice-events": "voice-events";
|
|
367
|
+
"contact-logs": "contact-logs";
|
|
368
|
+
"meta-whatsapp": "meta-whatsapp";
|
|
369
|
+
"email-inbound": "email-inbound";
|
|
370
|
+
}>;
|
|
371
|
+
providerRef: z.ZodOptional<z.ZodString>;
|
|
372
|
+
providerAt: z.ZodOptional<z.ZodString>;
|
|
373
|
+
matched: z.ZodBoolean;
|
|
374
|
+
campaignId: z.ZodOptional<z.ZodString>;
|
|
375
|
+
portfolioAccountId: z.ZodOptional<z.ZodString>;
|
|
376
|
+
summary: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
377
|
+
}, z.core.$strip>], "kind">;
|
|
378
|
+
export type EngineEvent = z.infer<typeof engineEventSchema>;
|
|
379
|
+
/** `Omit` distributed over the union (a plain Omit collapses the discriminant). */
|
|
380
|
+
type DistOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
381
|
+
/** An event as emission sites provide it — the recorder fills the id/at/tickId/seq spine. */
|
|
382
|
+
export type EngineEventInput = DistOmit<EngineEvent, "id" | "at" | "tickId" | "seq">;
|
|
383
|
+
export type TickStartedEvent = z.infer<typeof tickStartedSchema>;
|
|
384
|
+
export type TickCompletedEvent = z.infer<typeof tickCompletedSchema>;
|
|
385
|
+
export type CampaignEvaluatedEvent = z.infer<typeof campaignEvaluatedSchema>;
|
|
386
|
+
export type AccountDecidedEvent = z.infer<typeof accountDecidedSchema>;
|
|
387
|
+
export type AttemptReservedEvent = z.infer<typeof attemptReservedSchema>;
|
|
388
|
+
export type DispatchRequestedEvent = z.infer<typeof dispatchRequestedSchema>;
|
|
389
|
+
export type DispatchSucceededEvent = z.infer<typeof dispatchSucceededSchema>;
|
|
390
|
+
export type DispatchFailedEvent = z.infer<typeof dispatchFailedSchema>;
|
|
391
|
+
export type ProviderEventEvent = z.infer<typeof providerEventSchema>;
|
|
392
|
+
/**
|
|
393
|
+
* Where engine events land. Prisma-backed in production, in-memory in tests,
|
|
394
|
+
* no-op when recording is disabled. Implementations MUST be best-effort: a
|
|
395
|
+
* failing sink is caught and logged by the caller and never fails a tick or a
|
|
396
|
+
* dispatch.
|
|
397
|
+
*/
|
|
398
|
+
export interface EngineEventSink {
|
|
399
|
+
record(events: EngineEvent[]): Promise<void>;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Mask a recipient identifier for the event stream. Phones keep the last 4
|
|
403
|
+
* characters; emails keep the first character of the local part and the domain.
|
|
404
|
+
*/
|
|
405
|
+
export declare function maskRecipient(to: string): string;
|
|
406
|
+
export {};
|
|
407
|
+
//# sourceMappingURL=engineEvents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engineEvents.d.ts","sourceRoot":"","sources":["../../src/schemas/engineEvents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { dispatchChannelSchema } from "./dispatch.js";
|
|
3
|
+
/**
|
|
4
|
+
* Engine flight-recorder events. The engine (and the inbound provider webhooks)
|
|
5
|
+
* emit these as an append-only stream; the pure evaluator in `../evaluation/`
|
|
6
|
+
* replays a stream to prove a run stayed within parameters. Events are
|
|
7
|
+
* self-contained: `campaign.evaluated` snapshots the config in force that tick,
|
|
8
|
+
* so evaluating never requires reading live campaign rows.
|
|
9
|
+
*
|
|
10
|
+
* Correlation spine: `tickId` + `seq` order events within a tick;
|
|
11
|
+
* `workspaceRef`/`campaignId`/`portfolioAccountId`/`providerRef` tie them to the
|
|
12
|
+
* domain. Only tick lifecycle events are deployment-level (one engine loop ticks
|
|
13
|
+
* across all workspaces) — everything else carries `workspaceRef`.
|
|
14
|
+
*
|
|
15
|
+
* Privacy: recipient identifiers are masked (see `maskRecipient`); rendered
|
|
16
|
+
* bodies, scripts, and transcripts never enter the stream (they live on the
|
|
17
|
+
* gestión).
|
|
18
|
+
*/
|
|
19
|
+
export const engineEventKindSchema = z.enum([
|
|
20
|
+
"tick.started",
|
|
21
|
+
"tick.completed",
|
|
22
|
+
"campaign.evaluated",
|
|
23
|
+
"account.decided",
|
|
24
|
+
"attempt.reserved",
|
|
25
|
+
"dispatch.requested",
|
|
26
|
+
"dispatch.succeeded",
|
|
27
|
+
"dispatch.failed",
|
|
28
|
+
"provider.event"
|
|
29
|
+
]);
|
|
30
|
+
/** Fields every event carries; the correlation spine. */
|
|
31
|
+
const eventBase = z.object({
|
|
32
|
+
/** Unique event id (uuid or `<tickId>#<seq>`); violations reference these. */
|
|
33
|
+
id: z.string().min(1),
|
|
34
|
+
/** Event instant (engine clock for tick events, receipt time for provider events), ISO. */
|
|
35
|
+
at: z.string().min(1),
|
|
36
|
+
/** The tick this event belongs to; absent on provider events (they arrive between ticks). */
|
|
37
|
+
tickId: z.string().optional(),
|
|
38
|
+
/** Monotonic order within the tick. */
|
|
39
|
+
seq: z.number().int().nonnegative().optional()
|
|
40
|
+
});
|
|
41
|
+
/** Spine fields for events owned by a workspace (all non-tick events). */
|
|
42
|
+
const workspaceScoped = eventBase.extend({
|
|
43
|
+
workspaceRef: z.string().min(1)
|
|
44
|
+
});
|
|
45
|
+
/** Per-channel numbers keyed by engine channel. */
|
|
46
|
+
const perChannel = (value) => z.partialRecord(dispatchChannelSchema, value);
|
|
47
|
+
/** Snapshot of the campaign parameters in force during a tick (self-contained stream). */
|
|
48
|
+
export const campaignSnapshotSchema = z.object({
|
|
49
|
+
status: z.string(),
|
|
50
|
+
/** Local calendar bounds as ISO instants (the engine's stored campaign dates). */
|
|
51
|
+
startDate: z.string(),
|
|
52
|
+
endDate: z.string().nullable(),
|
|
53
|
+
/** ISO weekdays (1 = Monday … 7 = Sunday). */
|
|
54
|
+
daysOfWeek: z.array(z.number().int().min(1).max(7)),
|
|
55
|
+
/** Local wall-clock bounds, `HH:MM` 24h. */
|
|
56
|
+
startTime: z.string(),
|
|
57
|
+
endTime: z.string(),
|
|
58
|
+
maxAttemptsPerAccount: z.number().int().nonnegative(),
|
|
59
|
+
maxAttemptsPerDay: z.number().int().nonnegative(),
|
|
60
|
+
/** IANA timezone of the campaign's workspace (drives window + daily-cap math). */
|
|
61
|
+
timezone: z.string(),
|
|
62
|
+
channel: dispatchChannelSchema.nullable()
|
|
63
|
+
});
|
|
64
|
+
const tickStartedSchema = eventBase.extend({
|
|
65
|
+
kind: z.literal("tick.started"),
|
|
66
|
+
/** Tokens granted per channel this tick (perTickCapacity of the per-minute rates). */
|
|
67
|
+
budgets: perChannel(z.number().int().nonnegative()),
|
|
68
|
+
/** The deployment-wide per-tick dispatch cap, when configured. */
|
|
69
|
+
perTickMax: z.number().int().nonnegative().optional()
|
|
70
|
+
});
|
|
71
|
+
const tickCompletedSchema = eventBase.extend({
|
|
72
|
+
kind: z.literal("tick.completed"),
|
|
73
|
+
durationMs: z.number().nonnegative(),
|
|
74
|
+
/** Total dispatches across all workspaces this tick. */
|
|
75
|
+
dispatched: z.number().int().nonnegative(),
|
|
76
|
+
/** Whether the deployment-wide per-tick cap was hit (skews budget-utilization checks). */
|
|
77
|
+
perTickMaxReached: z.boolean(),
|
|
78
|
+
/**
|
|
79
|
+
* Tokens consumed vs granted per bucket (`dispatched` = consumed — a failed
|
|
80
|
+
* dispatch still spends its token). The voice channels share one bucket whose
|
|
81
|
+
* consumption is reported on VOICE_AI.
|
|
82
|
+
*/
|
|
83
|
+
channelUsage: perChannel(z.object({ dispatched: z.number().int().nonnegative(), budget: z.number().int().nonnegative() }))
|
|
84
|
+
});
|
|
85
|
+
const campaignEvaluatedSchema = workspaceScoped.extend({
|
|
86
|
+
kind: z.literal("campaign.evaluated"),
|
|
87
|
+
campaignId: z.string().min(1),
|
|
88
|
+
/** Display name at evaluation time — scorecards read it so consumers never join back. */
|
|
89
|
+
campaignName: z.string().optional(),
|
|
90
|
+
inWindow: z.boolean(),
|
|
91
|
+
skipReason: z.string().optional(),
|
|
92
|
+
/** Set when the engine auto-completed the campaign this tick. */
|
|
93
|
+
completed: z.boolean().optional(),
|
|
94
|
+
/** Candidates loaded for the campaign (0 when skipped before loading). */
|
|
95
|
+
candidateCount: z.number().int().nonnegative(),
|
|
96
|
+
snapshot: campaignSnapshotSchema
|
|
97
|
+
});
|
|
98
|
+
const accountDecidedSchema = workspaceScoped.extend({
|
|
99
|
+
kind: z.literal("account.decided"),
|
|
100
|
+
campaignId: z.string().min(1),
|
|
101
|
+
portfolioAccountId: z.string().min(1),
|
|
102
|
+
/** An `AccountDecision` (`dispatched`, `budget_exhausted`, suppression reasons, …). */
|
|
103
|
+
decision: z.string().min(1),
|
|
104
|
+
providerRef: z.string().optional()
|
|
105
|
+
});
|
|
106
|
+
const attemptReservedSchema = workspaceScoped.extend({
|
|
107
|
+
kind: z.literal("attempt.reserved"),
|
|
108
|
+
campaignId: z.string().min(1),
|
|
109
|
+
portfolioAccountId: z.string().min(1)
|
|
110
|
+
});
|
|
111
|
+
const dispatchRequestedSchema = workspaceScoped.extend({
|
|
112
|
+
kind: z.literal("dispatch.requested"),
|
|
113
|
+
campaignId: z.string().min(1),
|
|
114
|
+
portfolioAccountId: z.string().min(1),
|
|
115
|
+
channel: dispatchChannelSchema,
|
|
116
|
+
/** Masked recipient (see `maskRecipient`) — never the full identifier. */
|
|
117
|
+
toMasked: z.string()
|
|
118
|
+
});
|
|
119
|
+
const dispatchSucceededSchema = workspaceScoped.extend({
|
|
120
|
+
kind: z.literal("dispatch.succeeded"),
|
|
121
|
+
campaignId: z.string().min(1),
|
|
122
|
+
portfolioAccountId: z.string().min(1),
|
|
123
|
+
channel: dispatchChannelSchema,
|
|
124
|
+
providerRef: z.string().min(1),
|
|
125
|
+
latencyMs: z.number().nonnegative(),
|
|
126
|
+
toMasked: z.string()
|
|
127
|
+
});
|
|
128
|
+
const dispatchFailedSchema = workspaceScoped.extend({
|
|
129
|
+
kind: z.literal("dispatch.failed"),
|
|
130
|
+
campaignId: z.string().min(1),
|
|
131
|
+
portfolioAccountId: z.string().min(1),
|
|
132
|
+
channel: dispatchChannelSchema,
|
|
133
|
+
latencyMs: z.number().nonnegative(),
|
|
134
|
+
/** Coarse classification (the error's constructor name or "Error"). */
|
|
135
|
+
errorClass: z.string(),
|
|
136
|
+
errorMessage: z.string(),
|
|
137
|
+
toMasked: z.string()
|
|
138
|
+
});
|
|
139
|
+
const providerEventSchema = eventBase.extend({
|
|
140
|
+
kind: z.literal("provider.event"),
|
|
141
|
+
/** Owning workspace, resolved from the matched gestión; absent when unmatched. */
|
|
142
|
+
workspaceRef: z.string().optional(),
|
|
143
|
+
/** Which inbound surface received it. */
|
|
144
|
+
source: z.enum(["voice-events", "contact-logs", "meta-whatsapp", "email-inbound"]),
|
|
145
|
+
providerRef: z.string().optional(),
|
|
146
|
+
/** Provider-side timestamp when the payload carries one (receipt time is `at`). */
|
|
147
|
+
providerAt: z.string().optional(),
|
|
148
|
+
/** Whether the ref matched a known gestión. */
|
|
149
|
+
matched: z.boolean(),
|
|
150
|
+
campaignId: z.string().optional(),
|
|
151
|
+
portfolioAccountId: z.string().optional(),
|
|
152
|
+
/** Compact, content-free summary (event type, status, duration — never transcripts). */
|
|
153
|
+
summary: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional()
|
|
154
|
+
});
|
|
155
|
+
export const engineEventSchema = z.discriminatedUnion("kind", [
|
|
156
|
+
tickStartedSchema,
|
|
157
|
+
tickCompletedSchema,
|
|
158
|
+
campaignEvaluatedSchema,
|
|
159
|
+
accountDecidedSchema,
|
|
160
|
+
attemptReservedSchema,
|
|
161
|
+
dispatchRequestedSchema,
|
|
162
|
+
dispatchSucceededSchema,
|
|
163
|
+
dispatchFailedSchema,
|
|
164
|
+
providerEventSchema
|
|
165
|
+
]);
|
|
166
|
+
/**
|
|
167
|
+
* Mask a recipient identifier for the event stream. Phones keep the last 4
|
|
168
|
+
* characters; emails keep the first character of the local part and the domain.
|
|
169
|
+
*/
|
|
170
|
+
export function maskRecipient(to) {
|
|
171
|
+
const at = to.indexOf("@");
|
|
172
|
+
if (at > 0) {
|
|
173
|
+
return `${to[0]}***@${to.slice(at + 1)}`;
|
|
174
|
+
}
|
|
175
|
+
if (to.length <= 4)
|
|
176
|
+
return "*".repeat(to.length);
|
|
177
|
+
return `${"*".repeat(to.length - 4)}${to.slice(-4)}`;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=engineEvents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engineEvents.js","sourceRoot":"","sources":["../../src/schemas/engineEvents.ts"],"names":[],"mappings":"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"}
|