@defai.digital/feedback-domain 13.4.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,160 @@
1
+ /**
2
+ * Feedback Domain Types
3
+ *
4
+ * Port interfaces for the feedback learning system.
5
+ */
6
+ import type { FeedbackRecord, SubmitFeedbackInput, AgentScoreAdjustment, TaskPattern, AgentFeedbackStats, FeedbackOverview, FeedbackLearningConfig } from '@defai.digital/contracts';
7
+ /**
8
+ * Port for storing feedback records
9
+ */
10
+ export interface FeedbackStoragePort {
11
+ /**
12
+ * Store a feedback record
13
+ * INV-FBK-001: Records are immutable after storage
14
+ */
15
+ store(record: FeedbackRecord): Promise<void>;
16
+ /**
17
+ * Get feedback by ID
18
+ */
19
+ get(feedbackId: string): Promise<FeedbackRecord | null>;
20
+ /**
21
+ * List feedback records with optional filters
22
+ */
23
+ list(options?: {
24
+ agentId?: string;
25
+ limit?: number;
26
+ offset?: number;
27
+ since?: string;
28
+ }): Promise<FeedbackRecord[]>;
29
+ /**
30
+ * Count feedback records
31
+ */
32
+ count(options?: {
33
+ agentId?: string;
34
+ since?: string;
35
+ }): Promise<number>;
36
+ /**
37
+ * Delete old feedback records
38
+ * INV-FBK-301: Retention policy enforced
39
+ */
40
+ deleteOlderThan(date: string): Promise<number>;
41
+ }
42
+ /**
43
+ * Port for storing score adjustments
44
+ */
45
+ export interface ScoreAdjustmentStoragePort {
46
+ /**
47
+ * Get adjustment for agent and pattern
48
+ */
49
+ get(agentId: string, taskPattern: string): Promise<AgentScoreAdjustment | null>;
50
+ /**
51
+ * Save or update adjustment
52
+ */
53
+ set(adjustment: AgentScoreAdjustment): Promise<void>;
54
+ /**
55
+ * List all adjustments for an agent
56
+ */
57
+ listForAgent(agentId: string): Promise<AgentScoreAdjustment[]>;
58
+ /**
59
+ * Delete expired adjustments
60
+ */
61
+ deleteExpired(): Promise<number>;
62
+ }
63
+ /**
64
+ * Port for pattern matching
65
+ */
66
+ export interface PatternMatcherPort {
67
+ /**
68
+ * Find matching patterns for a task
69
+ */
70
+ findMatches(taskDescription: string, threshold: number): Promise<TaskPattern[]>;
71
+ /**
72
+ * Create or update a pattern
73
+ */
74
+ upsertPattern(pattern: TaskPattern): Promise<void>;
75
+ /**
76
+ * Get pattern by ID
77
+ */
78
+ getPattern(patternId: string): Promise<TaskPattern | null>;
79
+ }
80
+ /**
81
+ * Feedback collector options
82
+ */
83
+ export interface FeedbackCollectorOptions {
84
+ /**
85
+ * Feedback storage port
86
+ */
87
+ storage: FeedbackStoragePort;
88
+ /**
89
+ * Learning configuration
90
+ */
91
+ config?: FeedbackLearningConfig;
92
+ }
93
+ /**
94
+ * Score adjuster options
95
+ */
96
+ export interface ScoreAdjusterOptions {
97
+ /**
98
+ * Feedback storage port
99
+ */
100
+ feedbackStorage: FeedbackStoragePort;
101
+ /**
102
+ * Score adjustment storage port
103
+ */
104
+ adjustmentStorage: ScoreAdjustmentStoragePort;
105
+ /**
106
+ * Pattern matcher port
107
+ */
108
+ patternMatcher: PatternMatcherPort;
109
+ /**
110
+ * Learning configuration
111
+ */
112
+ config?: FeedbackLearningConfig;
113
+ }
114
+ /**
115
+ * Feedback collector interface
116
+ */
117
+ export interface FeedbackCollector {
118
+ /**
119
+ * Submit feedback
120
+ */
121
+ submit(input: SubmitFeedbackInput): Promise<FeedbackRecord>;
122
+ /**
123
+ * Get feedback history
124
+ */
125
+ getHistory(options?: {
126
+ agentId?: string;
127
+ limit?: number;
128
+ since?: string;
129
+ }): Promise<FeedbackRecord[]>;
130
+ /**
131
+ * Get feedback statistics for an agent
132
+ */
133
+ getAgentStats(agentId: string): Promise<AgentFeedbackStats>;
134
+ /**
135
+ * Get overall feedback overview
136
+ */
137
+ getOverview(): Promise<FeedbackOverview>;
138
+ }
139
+ /**
140
+ * Score adjuster interface
141
+ */
142
+ export interface ScoreAdjuster {
143
+ /**
144
+ * Get score adjustment for an agent and task
145
+ */
146
+ getAdjustment(agentId: string, taskDescription: string): Promise<number>;
147
+ /**
148
+ * Update adjustments based on new feedback
149
+ */
150
+ processNewFeedback(record: FeedbackRecord): Promise<void>;
151
+ /**
152
+ * Get all adjustments for an agent
153
+ */
154
+ getAgentAdjustments(agentId: string): Promise<AgentScoreAdjustment[]>;
155
+ /**
156
+ * Apply decay to all adjustments
157
+ */
158
+ applyDecay(): Promise<void>;
159
+ }
160
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Feedback Domain Types
3
+ *
4
+ * Port interfaces for the feedback learning system.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@defai.digital/feedback-domain",
3
+ "version": "13.4.0",
4
+ "description": "Agent feedback collection and learning system",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "dependencies": {
15
+ "@defai.digital/contracts": "13.4.0"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.6.3"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "src"
23
+ ],
24
+ "license": "MIT",
25
+ "scripts": {
26
+ "build": "tsc --build",
27
+ "clean": "rm -rf dist tsconfig.tsbuildinfo"
28
+ }
29
+ }
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Feedback Collector
3
+ *
4
+ * Collect and store feedback records.
5
+ *
6
+ * Invariants:
7
+ * - INV-FBK-001: Feedback records immutable
8
+ * - INV-FBK-100: No duplicate feedback
9
+ */
10
+
11
+ import type {
12
+ FeedbackRecord,
13
+ SubmitFeedbackInput,
14
+ AgentFeedbackStats,
15
+ FeedbackOverview,
16
+ } from '@defai.digital/contracts';
17
+ import {
18
+ createDefaultFeedbackLearningConfig,
19
+ createTaskHash,
20
+ } from '@defai.digital/contracts';
21
+ import type {
22
+ FeedbackCollector,
23
+ FeedbackCollectorOptions,
24
+ FeedbackStoragePort,
25
+ } from './types.js';
26
+
27
+ /**
28
+ * Create in-memory feedback storage
29
+ */
30
+ export function createInMemoryFeedbackStorage(): FeedbackStoragePort {
31
+ const records = new Map<string, FeedbackRecord>();
32
+
33
+ return {
34
+ async store(record: FeedbackRecord): Promise<void> {
35
+ // INV-FBK-001: Records are immutable - just store, never update
36
+ records.set(record.feedbackId, record);
37
+ },
38
+
39
+ async get(feedbackId: string): Promise<FeedbackRecord | null> {
40
+ return records.get(feedbackId) ?? null;
41
+ },
42
+
43
+ async list(options?: {
44
+ agentId?: string;
45
+ limit?: number;
46
+ offset?: number;
47
+ since?: string;
48
+ }): Promise<FeedbackRecord[]> {
49
+ let results = Array.from(records.values());
50
+
51
+ // Filter by agent
52
+ if (options?.agentId) {
53
+ results = results.filter((r) => r.selectedAgent === options.agentId);
54
+ }
55
+
56
+ // Filter by date
57
+ if (options?.since) {
58
+ const sinceDate = new Date(options.since);
59
+ results = results.filter((r) => new Date(r.timestamp) >= sinceDate);
60
+ }
61
+
62
+ // Sort by timestamp (newest first)
63
+ results.sort(
64
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
65
+ );
66
+
67
+ // Apply pagination
68
+ const offset = options?.offset ?? 0;
69
+ const limit = options?.limit ?? 100;
70
+ return results.slice(offset, offset + limit);
71
+ },
72
+
73
+ async count(options?: { agentId?: string; since?: string }): Promise<number> {
74
+ let count = 0;
75
+ for (const record of records.values()) {
76
+ if (options?.agentId && record.selectedAgent !== options.agentId) {
77
+ continue;
78
+ }
79
+ if (options?.since && new Date(record.timestamp) < new Date(options.since)) {
80
+ continue;
81
+ }
82
+ count++;
83
+ }
84
+ return count;
85
+ },
86
+
87
+ async deleteOlderThan(date: string): Promise<number> {
88
+ const threshold = new Date(date);
89
+ let deleted = 0;
90
+ for (const [id, record] of records) {
91
+ if (new Date(record.timestamp) < threshold) {
92
+ records.delete(id);
93
+ deleted++;
94
+ }
95
+ }
96
+ return deleted;
97
+ },
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Create feedback collector
103
+ */
104
+ export function createFeedbackCollector(
105
+ options: FeedbackCollectorOptions
106
+ ): FeedbackCollector {
107
+ const { storage } = options;
108
+ // Config is available for future use - call it to get defaults
109
+ void (options.config ?? createDefaultFeedbackLearningConfig());
110
+
111
+ // Track recent submissions for deduplication
112
+ // INV-FBK-100: No duplicate feedback
113
+ const recentSubmissions = new Map<string, number>();
114
+ const DEDUP_WINDOW_MS = 60000; // 1 minute
115
+
116
+ return {
117
+ async submit(input: SubmitFeedbackInput): Promise<FeedbackRecord> {
118
+ // INV-FBK-100: Check for duplicates
119
+ const dedupKey = `${input.selectedAgent}:${createTaskHash(input.taskDescription)}`;
120
+ const lastSubmit = recentSubmissions.get(dedupKey);
121
+ const now = Date.now();
122
+
123
+ if (lastSubmit && now - lastSubmit < DEDUP_WINDOW_MS) {
124
+ throw new Error('Duplicate feedback submission detected');
125
+ }
126
+
127
+ // Create feedback record
128
+ const record: FeedbackRecord = {
129
+ feedbackId: crypto.randomUUID(),
130
+ taskDescription: input.taskDescription,
131
+ taskHash: createTaskHash(input.taskDescription),
132
+ selectedAgent: input.selectedAgent,
133
+ feedbackType: input.feedbackType,
134
+ timestamp: new Date().toISOString(),
135
+ retryCount: 0,
136
+ };
137
+
138
+ // Add optional fields only if defined
139
+ if (input.recommendedAgent !== undefined) {
140
+ record.recommendedAgent = input.recommendedAgent;
141
+ }
142
+ if (input.rating !== undefined) {
143
+ record.rating = input.rating;
144
+ }
145
+ if (input.outcome !== undefined) {
146
+ record.outcome = input.outcome;
147
+ }
148
+ if (input.durationMs !== undefined) {
149
+ record.durationMs = input.durationMs;
150
+ }
151
+ if (input.userComment !== undefined) {
152
+ record.userComment = input.userComment;
153
+ }
154
+ if (input.sessionId !== undefined) {
155
+ record.sessionId = input.sessionId;
156
+ }
157
+
158
+ // Store the record
159
+ // INV-FBK-001: Immutable after this point
160
+ await storage.store(record);
161
+
162
+ // Track for deduplication
163
+ recentSubmissions.set(dedupKey, now);
164
+
165
+ // Cleanup old dedup entries - collect keys first to avoid concurrent modification
166
+ const keysToDelete: string[] = [];
167
+ for (const [key, time] of recentSubmissions) {
168
+ if (now - time > DEDUP_WINDOW_MS) {
169
+ keysToDelete.push(key);
170
+ }
171
+ }
172
+ for (const key of keysToDelete) {
173
+ recentSubmissions.delete(key);
174
+ }
175
+
176
+ return record;
177
+ },
178
+
179
+ async getHistory(options?: {
180
+ agentId?: string;
181
+ limit?: number;
182
+ since?: string;
183
+ }): Promise<FeedbackRecord[]> {
184
+ return storage.list(options);
185
+ },
186
+
187
+ async getAgentStats(agentId: string): Promise<AgentFeedbackStats> {
188
+ const records = await storage.list({ agentId });
189
+
190
+ const totalFeedback = records.length;
191
+ const ratings = records.filter((r) => r.rating !== undefined).map((r) => r.rating!);
192
+ const avgRating =
193
+ ratings.length > 0 ? ratings.reduce((a, b) => a + b, 0) / ratings.length : undefined;
194
+
195
+ const outcomes = records.filter((r) => r.outcome !== undefined);
196
+ const successCount = outcomes.filter((r) => r.outcome === 'success').length;
197
+ const successRate = outcomes.length > 0 ? successCount / outcomes.length : 1;
198
+
199
+ const recommended = records.filter((r) => r.recommendedAgent !== undefined);
200
+ const acceptedCount = recommended.filter(
201
+ (r) => r.recommendedAgent === r.selectedAgent
202
+ ).length;
203
+ const recommendationAcceptRate =
204
+ recommended.length > 0 ? acceptedCount / recommended.length : 1;
205
+
206
+ const durations = records
207
+ .filter((r) => r.durationMs !== undefined)
208
+ .map((r) => r.durationMs!);
209
+ const avgDurationMs =
210
+ durations.length > 0
211
+ ? durations.reduce((a, b) => a + b, 0) / durations.length
212
+ : undefined;
213
+
214
+ // Extract top patterns
215
+ const patternCounts = new Map<string, number>();
216
+ for (const record of records) {
217
+ const count = patternCounts.get(record.taskHash) ?? 0;
218
+ patternCounts.set(record.taskHash, count + 1);
219
+ }
220
+ const topPatterns = Array.from(patternCounts.entries())
221
+ .sort((a, b) => b[1] - a[1])
222
+ .slice(0, 10)
223
+ .map(([pattern]) => pattern);
224
+
225
+ const lastFeedback =
226
+ records.length > 0
227
+ ? records.reduce((latest, r) =>
228
+ new Date(r.timestamp) > new Date(latest.timestamp) ? r : latest
229
+ ).timestamp
230
+ : undefined;
231
+
232
+ return {
233
+ agentId,
234
+ totalFeedback,
235
+ avgRating,
236
+ successRate,
237
+ recommendationAcceptRate,
238
+ avgDurationMs,
239
+ topPatterns,
240
+ lastFeedback,
241
+ };
242
+ },
243
+
244
+ async getOverview(): Promise<FeedbackOverview> {
245
+ const allRecords = await storage.list({ limit: 10000 });
246
+ const totalFeedback = allRecords.length;
247
+
248
+ // Count by type
249
+ const feedbackByType: Record<string, number> = {
250
+ explicit: 0,
251
+ implicit: 0,
252
+ outcome: 0,
253
+ };
254
+ for (const record of allRecords) {
255
+ feedbackByType[record.feedbackType] =
256
+ (feedbackByType[record.feedbackType] ?? 0) + 1;
257
+ }
258
+
259
+ // Average rating
260
+ const ratings = allRecords
261
+ .filter((r) => r.rating !== undefined)
262
+ .map((r) => r.rating!);
263
+ const avgRating =
264
+ ratings.length > 0 ? ratings.reduce((a, b) => a + b, 0) / ratings.length : undefined;
265
+
266
+ // Success rate
267
+ const outcomes = allRecords.filter((r) => r.outcome !== undefined);
268
+ const successCount = outcomes.filter((r) => r.outcome === 'success').length;
269
+ const overallSuccessRate = outcomes.length > 0 ? successCount / outcomes.length : 1;
270
+
271
+ // Top agents
272
+ const agentScores = new Map<string, number>();
273
+ for (const record of allRecords) {
274
+ const score = agentScores.get(record.selectedAgent) ?? 0;
275
+ const delta = record.rating ?? (record.outcome === 'success' ? 5 : 1);
276
+ agentScores.set(record.selectedAgent, score + delta);
277
+ }
278
+ const topAgents = Array.from(agentScores.entries())
279
+ .sort((a, b) => b[1] - a[1])
280
+ .slice(0, 10)
281
+ .map(([agentId, score]) => ({ agentId, score }));
282
+
283
+ // Calculate trend (simplified)
284
+ const recentRecords = allRecords.slice(0, 20);
285
+ const olderRecords = allRecords.slice(20, 40);
286
+ const recentSuccessRate =
287
+ recentRecords.length > 0
288
+ ? recentRecords.filter((r) => r.outcome === 'success').length / recentRecords.length
289
+ : 1;
290
+ const olderSuccessRate =
291
+ olderRecords.length > 0
292
+ ? olderRecords.filter((r) => r.outcome === 'success').length / olderRecords.length
293
+ : 1;
294
+
295
+ let recentTrend: 'improving' | 'stable' | 'declining' = 'stable';
296
+ if (recentSuccessRate > olderSuccessRate + 0.1) {
297
+ recentTrend = 'improving';
298
+ } else if (recentSuccessRate < olderSuccessRate - 0.1) {
299
+ recentTrend = 'declining';
300
+ }
301
+
302
+ return {
303
+ totalFeedback,
304
+ feedbackByType: feedbackByType as Record<'explicit' | 'implicit' | 'outcome', number>,
305
+ avgRating,
306
+ overallSuccessRate,
307
+ topAgents,
308
+ recentTrend,
309
+ lastUpdated: new Date().toISOString(),
310
+ };
311
+ },
312
+ };
313
+ }
package/src/index.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Feedback Learning Domain
3
+ *
4
+ * Agent feedback collection and learning system.
5
+ */
6
+
7
+ // Types
8
+ export type {
9
+ FeedbackStoragePort,
10
+ ScoreAdjustmentStoragePort,
11
+ PatternMatcherPort,
12
+ FeedbackCollectorOptions,
13
+ ScoreAdjusterOptions,
14
+ FeedbackCollector,
15
+ ScoreAdjuster,
16
+ } from './types.js';
17
+
18
+ // Feedback Collector
19
+ export {
20
+ createFeedbackCollector,
21
+ createInMemoryFeedbackStorage,
22
+ } from './feedback-collector.js';
23
+
24
+ // Score Adjuster
25
+ export {
26
+ createScoreAdjuster,
27
+ createInMemoryAdjustmentStorage,
28
+ createSimplePatternMatcher,
29
+ } from './score-adjuster.js';