@operor/copilot 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.
@@ -0,0 +1,282 @@
1
+ import { KnowledgeBaseRuntime } from "@operor/core";
2
+
3
+ //#region src/types.d.ts
4
+ /**
5
+ * Training Copilot types
6
+ */
7
+ /** Status of an unanswered query through the review lifecycle */
8
+ type QueryStatus = 'pending' | 'taught' | 'dismissed';
9
+ /** A customer query that the KB couldn't confidently answer */
10
+ interface UnansweredQuery {
11
+ id: string;
12
+ query: string;
13
+ normalizedQuery: string;
14
+ channel: string;
15
+ customerPhone: string;
16
+ kbTopScore: number;
17
+ kbIsFaqMatch: boolean;
18
+ kbTopChunkContent?: string;
19
+ kbResultCount: number;
20
+ status: QueryStatus;
21
+ clusterId?: string;
22
+ timesAsked: number;
23
+ uniqueCustomers: string[];
24
+ embedding?: number[];
25
+ suggestedAnswer?: string;
26
+ taughtAnswer?: string;
27
+ createdAt: number;
28
+ updatedAt: number;
29
+ }
30
+ /** A cluster of semantically similar unanswered queries */
31
+ interface QueryCluster {
32
+ id: string;
33
+ label?: string;
34
+ representativeQuery: string;
35
+ centroid?: number[];
36
+ queryCount: number;
37
+ uniqueCustomers: string[];
38
+ status: QueryStatus;
39
+ createdAt: number;
40
+ updatedAt: number;
41
+ }
42
+ /** Aggregate metrics for the copilot dashboard / digest */
43
+ interface ImpactMetrics {
44
+ pendingCount: number;
45
+ taughtCount: number;
46
+ dismissedCount: number;
47
+ totalCustomersAffected: number;
48
+ totalTimesAsked: number;
49
+ topPendingQueries: UnansweredQuery[];
50
+ }
51
+ /** Configuration for the copilot subsystem */
52
+ interface CopilotConfig {
53
+ enabled: boolean;
54
+ trackingThreshold: number;
55
+ clusterThreshold: number;
56
+ digestIntervalMs: number;
57
+ digestMaxItems: number;
58
+ autoSuggest: boolean;
59
+ }
60
+ /** Default copilot configuration values */
61
+ declare const DEFAULT_COPILOT_CONFIG: CopilotConfig;
62
+ /** Embedding service interface — decouples copilot from specific embedding providers */
63
+ interface EmbeddingService {
64
+ embed(text: string): Promise<number[]>;
65
+ dimensions: number;
66
+ }
67
+ /** AI provider interface for suggestion generation */
68
+ interface AIProviderLike {
69
+ generateText(options: {
70
+ model?: string;
71
+ system?: string;
72
+ prompt: string;
73
+ maxTokens?: number;
74
+ temperature?: number;
75
+ }): Promise<{
76
+ text: string;
77
+ }>;
78
+ }
79
+ /** Store interface for copilot persistence */
80
+ interface CopilotStore {
81
+ initialize(): Promise<void>;
82
+ close(): Promise<void>;
83
+ addQuery(query: UnansweredQuery): Promise<void>;
84
+ getQuery(id: string): Promise<UnansweredQuery | null>;
85
+ updateQuery(id: string, updates: Partial<UnansweredQuery>): Promise<void>;
86
+ getPendingQueries(limit?: number): Promise<UnansweredQuery[]>;
87
+ findSimilarQuery(normalizedQuery: string): Promise<UnansweredQuery | null>;
88
+ getQueriesByCluster(clusterId: string): Promise<UnansweredQuery[]>;
89
+ addCluster(cluster: QueryCluster): Promise<void>;
90
+ getCluster(id: string): Promise<QueryCluster | null>;
91
+ updateCluster(id: string, updates: Partial<QueryCluster>): Promise<void>;
92
+ getOpenClusters(): Promise<QueryCluster[]>;
93
+ getImpactMetrics(topN?: number): Promise<ImpactMetrics>;
94
+ getLastDigestTime(): Promise<number>;
95
+ setLastDigestTime(time: number): Promise<void>;
96
+ }
97
+ /** Event emitted after a message is processed by the agent pipeline */
98
+ interface MessageProcessedEvent {
99
+ query: string;
100
+ channel: string;
101
+ customerPhone: string;
102
+ response: {
103
+ text: string;
104
+ metadata?: {
105
+ kbTopScore?: number;
106
+ kbIsFaqMatch?: boolean;
107
+ kbTopChunkContent?: string;
108
+ kbResultCount?: number;
109
+ };
110
+ };
111
+ }
112
+ //#endregion
113
+ //#region src/SQLiteCopilotStore.d.ts
114
+ /**
115
+ * SQLite-backed copilot store with sqlite-vec for vector search on cluster centroids.
116
+ */
117
+ declare class SQLiteCopilotStore implements CopilotStore {
118
+ private dbPath;
119
+ private dimensions;
120
+ private db;
121
+ constructor(dbPath: string, dimensions: number);
122
+ initialize(): Promise<void>;
123
+ close(): Promise<void>;
124
+ addQuery(query: UnansweredQuery): Promise<void>;
125
+ getQuery(id: string): Promise<UnansweredQuery | null>;
126
+ updateQuery(id: string, updates: Partial<UnansweredQuery>): Promise<void>;
127
+ getPendingQueries(limit?: number): Promise<UnansweredQuery[]>;
128
+ findSimilarQuery(normalizedQuery: string): Promise<UnansweredQuery | null>;
129
+ getQueriesByCluster(clusterId: string): Promise<UnansweredQuery[]>;
130
+ addCluster(cluster: QueryCluster): Promise<void>;
131
+ getCluster(id: string): Promise<QueryCluster | null>;
132
+ updateCluster(id: string, updates: Partial<QueryCluster>): Promise<void>;
133
+ getOpenClusters(): Promise<QueryCluster[]>;
134
+ /** Vector search cluster centroids — returns closest clusters by cosine distance */
135
+ searchClusters(embedding: number[], limit: number): Promise<Array<{
136
+ clusterId: string;
137
+ distance: number;
138
+ }>>;
139
+ getImpactMetrics(topN?: number): Promise<ImpactMetrics>;
140
+ getLastDigestTime(): Promise<number>;
141
+ setLastDigestTime(time: number): Promise<void>;
142
+ private rowToQuery;
143
+ private rowToCluster;
144
+ }
145
+ //#endregion
146
+ //#region src/InMemoryCopilotStore.d.ts
147
+ /**
148
+ * In-memory copilot store for testing and development.
149
+ */
150
+ declare class InMemoryCopilotStore implements CopilotStore {
151
+ private queries;
152
+ private clusters;
153
+ private lastDigestTime;
154
+ initialize(): Promise<void>;
155
+ close(): Promise<void>;
156
+ addQuery(query: UnansweredQuery): Promise<void>;
157
+ getQuery(id: string): Promise<UnansweredQuery | null>;
158
+ updateQuery(id: string, updates: Partial<UnansweredQuery>): Promise<void>;
159
+ getPendingQueries(limit?: number): Promise<UnansweredQuery[]>;
160
+ findSimilarQuery(normalizedQuery: string): Promise<UnansweredQuery | null>;
161
+ getQueriesByCluster(clusterId: string): Promise<UnansweredQuery[]>;
162
+ addCluster(cluster: QueryCluster): Promise<void>;
163
+ getCluster(id: string): Promise<QueryCluster | null>;
164
+ updateCluster(id: string, updates: Partial<QueryCluster>): Promise<void>;
165
+ getOpenClusters(): Promise<QueryCluster[]>;
166
+ getImpactMetrics(topN?: number): Promise<ImpactMetrics>;
167
+ getLastDigestTime(): Promise<number>;
168
+ setLastDigestTime(time: number): Promise<void>;
169
+ }
170
+ //#endregion
171
+ //#region src/QueryClusterer.d.ts
172
+ /**
173
+ * Groups semantically similar unanswered queries into clusters.
174
+ */
175
+ declare class QueryClusterer {
176
+ private store;
177
+ private embedder;
178
+ private config;
179
+ constructor(store: CopilotStore, embedder: EmbeddingService, config?: {
180
+ clusterThreshold: number;
181
+ });
182
+ /**
183
+ * Assign a query to an existing cluster or create a new one.
184
+ * Returns the cluster ID.
185
+ */
186
+ assignCluster(queryId: string, queryText: string, embedding: number[]): Promise<string>;
187
+ /** Cosine similarity between two vectors */
188
+ cosineSimilarity(a: number[], b: number[]): number;
189
+ /** Compute running average centroid */
190
+ updateCentroid(current: number[], newVec: number[], count: number): number[];
191
+ }
192
+ //#endregion
193
+ //#region src/UnansweredQueryTracker.d.ts
194
+ /**
195
+ * Tracks unanswered queries by listening to message:processed events.
196
+ * Runs non-blocking — errors are caught and logged, never thrown.
197
+ */
198
+ declare class UnansweredQueryTracker {
199
+ private store;
200
+ private config;
201
+ private embedder;
202
+ private clusterer?;
203
+ constructor(store: CopilotStore, config: {
204
+ enabled: boolean;
205
+ trackingThreshold: number;
206
+ }, embedder: EmbeddingService, clusterer?: QueryClusterer | undefined);
207
+ /**
208
+ * Called after each message is processed. Decides whether to track the query.
209
+ * Non-blocking: catches all errors internally.
210
+ */
211
+ maybeTrack(event: MessageProcessedEvent): Promise<void>;
212
+ /** Normalize query text for deduplication */
213
+ normalizeQuery(text: string): string;
214
+ }
215
+ //#endregion
216
+ //#region src/SuggestionEngine.d.ts
217
+ /**
218
+ * Generates suggested answers for unanswered queries using the LLM + KB context.
219
+ */
220
+ declare class SuggestionEngine {
221
+ private aiProvider;
222
+ private kb;
223
+ constructor(aiProvider: AIProviderLike, kb: KnowledgeBaseRuntime);
224
+ /**
225
+ * Generate a suggested answer for a query, optionally including related queries from a cluster.
226
+ */
227
+ suggest(query: string, relatedQueries?: string[]): Promise<string>;
228
+ }
229
+ //#endregion
230
+ //#region src/CopilotCommandHandler.d.ts
231
+ /**
232
+ * Handles /review commands from admin users in training mode.
233
+ */
234
+ declare class CopilotCommandHandler {
235
+ private store;
236
+ private suggestionEngine;
237
+ private kb;
238
+ private clusterer?;
239
+ /** Per-admin session state: tracks which query they're currently reviewing */
240
+ private sessions;
241
+ constructor(store: CopilotStore, suggestionEngine: SuggestionEngine | undefined, kb: KnowledgeBaseRuntime, clusterer?: QueryClusterer | undefined);
242
+ /**
243
+ * Handle a /review subcommand.
244
+ * @param command The full command (always '/review')
245
+ * @param args Subcommand + arguments (e.g. 'accept This is the answer')
246
+ * @param adminPhone The admin's phone number
247
+ * @param reply Function to send a reply back to the admin
248
+ */
249
+ handleCommand(command: string, args: string, adminPhone: string, reply: (text: string) => Promise<void>): Promise<void>;
250
+ private getSession;
251
+ private handleNext;
252
+ private handleAccept;
253
+ private handleEdit;
254
+ private handleSkip;
255
+ private handleStats;
256
+ private handleCluster;
257
+ private handleHelp;
258
+ }
259
+ //#endregion
260
+ //#region src/DigestScheduler.d.ts
261
+ /**
262
+ * Periodically sends digest summaries of unanswered queries to admin phones.
263
+ */
264
+ declare class DigestScheduler {
265
+ private store;
266
+ private config;
267
+ private sendMessage;
268
+ private timer;
269
+ constructor(store: CopilotStore, config: {
270
+ digestIntervalMs: number;
271
+ digestMaxItems: number;
272
+ }, sendMessage: (phone: string, text: string) => Promise<void>);
273
+ /** Start the digest scheduler for the given admin phones */
274
+ start(adminPhones: string[]): void;
275
+ /** Stop the digest scheduler */
276
+ stop(): void;
277
+ /** Build the digest message text */
278
+ buildDigest(): Promise<string | null>;
279
+ }
280
+ //#endregion
281
+ export { AIProviderLike, CopilotCommandHandler, CopilotConfig, CopilotStore, DEFAULT_COPILOT_CONFIG, DigestScheduler, EmbeddingService, ImpactMetrics, InMemoryCopilotStore, MessageProcessedEvent, QueryCluster, QueryClusterer, QueryStatus, SQLiteCopilotStore, SuggestionEngine, UnansweredQuery, UnansweredQueryTracker };
282
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/SQLiteCopilotStore.ts","../src/InMemoryCopilotStore.ts","../src/QueryClusterer.ts","../src/UnansweredQueryTracker.ts","../src/SuggestionEngine.ts","../src/CopilotCommandHandler.ts","../src/DigestScheduler.ts"],"mappings":"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"}