@operor/analytics 0.1.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/index.d.ts +224 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +571 -0
- package/dist/index.js.map +1 -0
- package/package.json +29 -0
- package/src/AnalyticsCollector.test.ts +344 -0
- package/src/AnalyticsCollector.ts +148 -0
- package/src/InMemoryAnalyticsStore.test.ts +495 -0
- package/src/InMemoryAnalyticsStore.ts +250 -0
- package/src/SQLiteAnalyticsStore.test.ts +554 -0
- package/src/SQLiteAnalyticsStore.ts +367 -0
- package/src/index.ts +4 -0
- package/src/types.ts +149 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.ts +10 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Analytics types for Operor
|
|
4
|
+
*/
|
|
5
|
+
/** A single message event recorded by the analytics collector */
|
|
6
|
+
interface AnalyticsEvent {
|
|
7
|
+
id?: number;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
channel: string;
|
|
10
|
+
customerPhone: string;
|
|
11
|
+
customerId: string;
|
|
12
|
+
agentName: string;
|
|
13
|
+
intent: string;
|
|
14
|
+
intentConfidence: number;
|
|
15
|
+
responseTimeMs: number;
|
|
16
|
+
llmCost: number;
|
|
17
|
+
kbTopScore: number;
|
|
18
|
+
kbIsFaqMatch: boolean;
|
|
19
|
+
kbResultCount: number;
|
|
20
|
+
toolCallsCount: number;
|
|
21
|
+
toolCallsJson: string | null;
|
|
22
|
+
messageLength: number;
|
|
23
|
+
responseLength: number;
|
|
24
|
+
isNewCustomer: boolean;
|
|
25
|
+
wasEscalated: boolean;
|
|
26
|
+
conversationId: string | null;
|
|
27
|
+
promptTokens: number;
|
|
28
|
+
completionTokens: number;
|
|
29
|
+
}
|
|
30
|
+
/** Aggregated summary for a time range */
|
|
31
|
+
interface AnalyticsSummary {
|
|
32
|
+
totalMessages: number;
|
|
33
|
+
avgPerDay: number;
|
|
34
|
+
peakDay: string | null;
|
|
35
|
+
kbAnsweredPct: number;
|
|
36
|
+
llmFallbackPct: number;
|
|
37
|
+
noAnswerPct: number;
|
|
38
|
+
avgResponseTime: number;
|
|
39
|
+
faqHitRate: number;
|
|
40
|
+
uniqueCustomers: number;
|
|
41
|
+
newCustomers: number;
|
|
42
|
+
returningCustomers: number;
|
|
43
|
+
agentBreakdown: Record<string, number>;
|
|
44
|
+
pendingReviews: number;
|
|
45
|
+
}
|
|
46
|
+
/** Message volume data point (for charts) */
|
|
47
|
+
interface MessageVolumeData {
|
|
48
|
+
date: string;
|
|
49
|
+
count: number;
|
|
50
|
+
channel?: string;
|
|
51
|
+
}
|
|
52
|
+
/** Per-agent stats */
|
|
53
|
+
interface AgentStatsData {
|
|
54
|
+
agentName: string;
|
|
55
|
+
messageCount: number;
|
|
56
|
+
avgResponseTimeMs: number;
|
|
57
|
+
avgConfidence: number;
|
|
58
|
+
escalationCount: number;
|
|
59
|
+
toolCallCount: number;
|
|
60
|
+
}
|
|
61
|
+
/** Per-customer stats */
|
|
62
|
+
interface CustomerStatsData {
|
|
63
|
+
customerId: string;
|
|
64
|
+
customerPhone: string;
|
|
65
|
+
messageCount: number;
|
|
66
|
+
firstSeen: number;
|
|
67
|
+
lastSeen: number;
|
|
68
|
+
isNew: boolean;
|
|
69
|
+
}
|
|
70
|
+
/** Knowledge Base stats from analytics */
|
|
71
|
+
interface KbStatsData {
|
|
72
|
+
totalQueries: number;
|
|
73
|
+
faqHits: number;
|
|
74
|
+
faqHitRate: number;
|
|
75
|
+
avgTopScore: number;
|
|
76
|
+
topFaqHits: Array<{
|
|
77
|
+
intent: string;
|
|
78
|
+
count: number;
|
|
79
|
+
}>;
|
|
80
|
+
topMisses: Array<{
|
|
81
|
+
intent: string;
|
|
82
|
+
count: number;
|
|
83
|
+
avgScore: number;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
/** A conversation session (gap-based) */
|
|
87
|
+
interface ConversationSession {
|
|
88
|
+
id: string;
|
|
89
|
+
customerId: string;
|
|
90
|
+
customerPhone: string;
|
|
91
|
+
channel: string;
|
|
92
|
+
agentId: string;
|
|
93
|
+
startedAt: number;
|
|
94
|
+
endedAt: number;
|
|
95
|
+
messageCount: number;
|
|
96
|
+
toolCallCount: number;
|
|
97
|
+
totalDurationMs: number;
|
|
98
|
+
totalCost: number;
|
|
99
|
+
resolved: boolean;
|
|
100
|
+
resolutionType: string | null;
|
|
101
|
+
}
|
|
102
|
+
/** Time range filter for queries */
|
|
103
|
+
interface TimeRange {
|
|
104
|
+
from: number;
|
|
105
|
+
to: number;
|
|
106
|
+
}
|
|
107
|
+
/** Store interface for analytics persistence */
|
|
108
|
+
interface AnalyticsStore {
|
|
109
|
+
initialize(): Promise<void>;
|
|
110
|
+
close(): Promise<void>;
|
|
111
|
+
/** Record a message event */
|
|
112
|
+
recordMessageEvent(event: AnalyticsEvent): Promise<void>;
|
|
113
|
+
/** Get or create a conversation session */
|
|
114
|
+
getOrCreateConversation(customerPhone: string, channel: string, agentName: string): Promise<string>;
|
|
115
|
+
/** Update conversation stats after a message */
|
|
116
|
+
updateConversationStats(conversationId: string, event: AnalyticsEvent): Promise<void>;
|
|
117
|
+
/** Get aggregated summary for a time range */
|
|
118
|
+
getSummary(range?: TimeRange): Promise<AnalyticsSummary>;
|
|
119
|
+
/** Get message volume over time */
|
|
120
|
+
getMessageVolume(range?: TimeRange, groupBy?: 'day' | 'hour'): Promise<MessageVolumeData[]>;
|
|
121
|
+
/** Get per-agent stats */
|
|
122
|
+
getAgentStats(range?: TimeRange): Promise<AgentStatsData[]>;
|
|
123
|
+
/** Get per-customer stats */
|
|
124
|
+
getCustomerStats(range?: TimeRange, limit?: number): Promise<CustomerStatsData[]>;
|
|
125
|
+
/** Get KB-related stats */
|
|
126
|
+
getKbStats(range?: TimeRange): Promise<KbStatsData>;
|
|
127
|
+
/** Get top FAQ hits */
|
|
128
|
+
getTopFaqHits(limit?: number, range?: TimeRange): Promise<Array<{
|
|
129
|
+
intent: string;
|
|
130
|
+
count: number;
|
|
131
|
+
}>>;
|
|
132
|
+
/** Get top misses (low KB score) */
|
|
133
|
+
getTopMisses(limit?: number, range?: TimeRange): Promise<Array<{
|
|
134
|
+
intent: string;
|
|
135
|
+
count: number;
|
|
136
|
+
avgScore: number;
|
|
137
|
+
}>>;
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/SQLiteAnalyticsStore.d.ts
|
|
141
|
+
declare class SQLiteAnalyticsStore implements AnalyticsStore {
|
|
142
|
+
private db;
|
|
143
|
+
constructor(dbPath?: string);
|
|
144
|
+
initialize(): Promise<void>;
|
|
145
|
+
close(): Promise<void>;
|
|
146
|
+
recordMessageEvent(event: AnalyticsEvent): Promise<void>;
|
|
147
|
+
getOrCreateConversation(customerPhone: string, channel: string, agentName: string): Promise<string>;
|
|
148
|
+
updateConversationStats(conversationId: string, event: AnalyticsEvent): Promise<void>;
|
|
149
|
+
getSummary(range?: TimeRange): Promise<AnalyticsSummary>;
|
|
150
|
+
getMessageVolume(range?: TimeRange, groupBy?: 'day' | 'hour'): Promise<MessageVolumeData[]>;
|
|
151
|
+
getAgentStats(range?: TimeRange): Promise<AgentStatsData[]>;
|
|
152
|
+
getCustomerStats(range?: TimeRange, limit?: number): Promise<CustomerStatsData[]>;
|
|
153
|
+
getKbStats(range?: TimeRange): Promise<KbStatsData>;
|
|
154
|
+
getTopFaqHits(limit?: number, range?: TimeRange): Promise<Array<{
|
|
155
|
+
intent: string;
|
|
156
|
+
count: number;
|
|
157
|
+
}>>;
|
|
158
|
+
getTopMisses(limit?: number, range?: TimeRange): Promise<Array<{
|
|
159
|
+
intent: string;
|
|
160
|
+
count: number;
|
|
161
|
+
avgScore: number;
|
|
162
|
+
}>>;
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/InMemoryAnalyticsStore.d.ts
|
|
166
|
+
/**
|
|
167
|
+
* In-memory analytics store for testing and development.
|
|
168
|
+
*/
|
|
169
|
+
declare class InMemoryAnalyticsStore implements AnalyticsStore {
|
|
170
|
+
private events;
|
|
171
|
+
private conversations;
|
|
172
|
+
initialize(): Promise<void>;
|
|
173
|
+
close(): Promise<void>;
|
|
174
|
+
recordMessageEvent(event: AnalyticsEvent): Promise<void>;
|
|
175
|
+
getOrCreateConversation(customerPhone: string, channel: string, agentName: string): Promise<string>;
|
|
176
|
+
updateConversationStats(conversationId: string, event: AnalyticsEvent): Promise<void>;
|
|
177
|
+
private filter;
|
|
178
|
+
getSummary(range?: TimeRange): Promise<AnalyticsSummary>;
|
|
179
|
+
getMessageVolume(range?: TimeRange, groupBy?: 'day' | 'hour'): Promise<MessageVolumeData[]>;
|
|
180
|
+
getAgentStats(range?: TimeRange): Promise<AgentStatsData[]>;
|
|
181
|
+
getCustomerStats(range?: TimeRange, limit?: number): Promise<CustomerStatsData[]>;
|
|
182
|
+
getKbStats(range?: TimeRange): Promise<KbStatsData>;
|
|
183
|
+
getTopFaqHits(limit?: number, range?: TimeRange): Promise<Array<{
|
|
184
|
+
intent: string;
|
|
185
|
+
count: number;
|
|
186
|
+
}>>;
|
|
187
|
+
getTopMisses(limit?: number, range?: TimeRange): Promise<Array<{
|
|
188
|
+
intent: string;
|
|
189
|
+
count: number;
|
|
190
|
+
avgScore: number;
|
|
191
|
+
}>>;
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/AnalyticsCollector.d.ts
|
|
195
|
+
/** Minimal EventEmitter interface — matches eventemitter3 used by Operor */
|
|
196
|
+
interface Emitter {
|
|
197
|
+
on(event: string, handler: (...args: any[]) => void): void;
|
|
198
|
+
off(event: string, handler: (...args: any[]) => void): void;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Listens to Operor events and persists analytics data.
|
|
202
|
+
*/
|
|
203
|
+
declare class AnalyticsCollector {
|
|
204
|
+
private store;
|
|
205
|
+
private debug;
|
|
206
|
+
private boundHandlers;
|
|
207
|
+
constructor(store: AnalyticsStore, options?: {
|
|
208
|
+
debug?: boolean;
|
|
209
|
+
});
|
|
210
|
+
/**
|
|
211
|
+
* Attach to an Operor instance (or any EventEmitter with the same events).
|
|
212
|
+
*/
|
|
213
|
+
attach(os: Emitter): void;
|
|
214
|
+
/**
|
|
215
|
+
* Detach from an Operor instance.
|
|
216
|
+
*/
|
|
217
|
+
detach(os: Emitter): void;
|
|
218
|
+
private handleProcessed;
|
|
219
|
+
private handleError;
|
|
220
|
+
private log;
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
export { AgentStatsData, AnalyticsCollector, AnalyticsEvent, AnalyticsStore, AnalyticsSummary, ConversationSession, CustomerStatsData, InMemoryAnalyticsStore, KbStatsData, MessageVolumeData, SQLiteAnalyticsStore, TimeRange };
|
|
224
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/SQLiteAnalyticsStore.ts","../src/InMemoryAnalyticsStore.ts","../src/AnalyticsCollector.ts"],"mappings":"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"}
|