societyai 0.0.1

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.
Files changed (114) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +879 -0
  4. package/dist/builder.d.ts +181 -0
  5. package/dist/builder.d.ts.map +1 -0
  6. package/dist/builder.js +667 -0
  7. package/dist/builder.js.map +1 -0
  8. package/dist/config.d.ts +43 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/config.js +11 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/context.d.ts +107 -0
  13. package/dist/context.d.ts.map +1 -0
  14. package/dist/context.js +319 -0
  15. package/dist/context.js.map +1 -0
  16. package/dist/errors.d.ts +31 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +85 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/events.d.ts +219 -0
  21. package/dist/events.d.ts.map +1 -0
  22. package/dist/events.js +395 -0
  23. package/dist/events.js.map +1 -0
  24. package/dist/graph.d.ts +104 -0
  25. package/dist/graph.d.ts.map +1 -0
  26. package/dist/graph.js +366 -0
  27. package/dist/graph.js.map +1 -0
  28. package/dist/index.d.ts +28 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +113 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/logger.d.ts +13 -0
  33. package/dist/logger.d.ts.map +1 -0
  34. package/dist/logger.js +78 -0
  35. package/dist/logger.js.map +1 -0
  36. package/dist/memory.d.ts +146 -0
  37. package/dist/memory.d.ts.map +1 -0
  38. package/dist/memory.js +353 -0
  39. package/dist/memory.js.map +1 -0
  40. package/dist/metrics.d.ts +143 -0
  41. package/dist/metrics.d.ts.map +1 -0
  42. package/dist/metrics.js +271 -0
  43. package/dist/metrics.js.map +1 -0
  44. package/dist/middleware.d.ts +147 -0
  45. package/dist/middleware.d.ts.map +1 -0
  46. package/dist/middleware.js +484 -0
  47. package/dist/middleware.js.map +1 -0
  48. package/dist/models.d.ts +32 -0
  49. package/dist/models.d.ts.map +1 -0
  50. package/dist/models.js +211 -0
  51. package/dist/models.js.map +1 -0
  52. package/dist/patterns.d.ts +6 -0
  53. package/dist/patterns.d.ts.map +1 -0
  54. package/dist/patterns.js +68 -0
  55. package/dist/patterns.js.map +1 -0
  56. package/dist/pipeline.d.ts +84 -0
  57. package/dist/pipeline.d.ts.map +1 -0
  58. package/dist/pipeline.js +569 -0
  59. package/dist/pipeline.js.map +1 -0
  60. package/dist/retry.d.ts +5 -0
  61. package/dist/retry.d.ts.map +1 -0
  62. package/dist/retry.js +70 -0
  63. package/dist/retry.js.map +1 -0
  64. package/dist/society.d.ts +94 -0
  65. package/dist/society.d.ts.map +1 -0
  66. package/dist/society.js +721 -0
  67. package/dist/society.js.map +1 -0
  68. package/dist/strategies.d.ts +55 -0
  69. package/dist/strategies.d.ts.map +1 -0
  70. package/dist/strategies.js +678 -0
  71. package/dist/strategies.js.map +1 -0
  72. package/dist/tools.d.ts +88 -0
  73. package/dist/tools.d.ts.map +1 -0
  74. package/dist/tools.js +366 -0
  75. package/dist/tools.js.map +1 -0
  76. package/dist/types.d.ts +213 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +19 -0
  79. package/dist/types.js.map +1 -0
  80. package/dist/validation.d.ts +64 -0
  81. package/dist/validation.d.ts.map +1 -0
  82. package/dist/validation.js +334 -0
  83. package/dist/validation.js.map +1 -0
  84. package/dist/worker-pool.d.ts +17 -0
  85. package/dist/worker-pool.d.ts.map +1 -0
  86. package/dist/worker-pool.js +80 -0
  87. package/dist/worker-pool.js.map +1 -0
  88. package/docs/README.md +468 -0
  89. package/docs/advanced.md +616 -0
  90. package/docs/aggregation-strategies.md +926 -0
  91. package/docs/api-reference.md +771 -0
  92. package/docs/architecture.md +648 -0
  93. package/docs/context-system.md +642 -0
  94. package/docs/event-system.md +1047 -0
  95. package/docs/examples.md +576 -0
  96. package/docs/getting-started.md +564 -0
  97. package/docs/graph-execution.md +389 -0
  98. package/docs/memory-system.md +497 -0
  99. package/docs/metrics-observability.md +560 -0
  100. package/docs/middleware-system.md +1038 -0
  101. package/docs/migration.md +296 -0
  102. package/docs/pipeline-patterns.md +761 -0
  103. package/docs/structured-output.md +612 -0
  104. package/docs/tool-calling.md +491 -0
  105. package/docs/workflows.md +740 -0
  106. package/examples/README.md +234 -0
  107. package/examples/advanced-patterns.ts +115 -0
  108. package/examples/complete-integration.ts +327 -0
  109. package/examples/graph-workflow.ts +161 -0
  110. package/examples/memory-system.ts +155 -0
  111. package/examples/metrics-tracking.ts +243 -0
  112. package/examples/structured-output.ts +231 -0
  113. package/examples/tool-calling.ts +163 -0
  114. package/package.json +94 -0
@@ -0,0 +1,1047 @@
1
+ # Event System
2
+
3
+ Le système d'événements de SocietyAI fournit un mécanisme d'observation type-safe pour surveiller le cycle de vie des workflows, suivre la progression, et intégrer avec des systèmes externes.
4
+
5
+ ## Table des Matières
6
+
7
+ - [Vue d'ensemble](#vue-densemble)
8
+ - [Types d'Événements](#types-dévénements)
9
+ - [Event Emitter](#event-emitter)
10
+ - [Event Handlers](#event-handlers)
11
+ - [Progress Tracking](#progress-tracking)
12
+ - [Event Filtering](#event-filtering)
13
+ - [Event History](#event-history)
14
+ - [Intégrations](#intégrations)
15
+ - [Exemples Complets](#exemples-complets)
16
+
17
+ ## Vue d'ensemble
18
+
19
+ Le système d'événements permet de:
20
+
21
+ - **Observer le cycle de vie** des workflows, steps et agents
22
+ - **Suivre la progression** en temps réel
23
+ - **Déboguer** avec des hooks détaillés
24
+ - **Intégrer** avec des systèmes de logging/monitoring externes
25
+ - **Historique** des événements pour replay et analyse
26
+
27
+ ### Principes de Design
28
+
29
+ - **Type-safe**: Support complet TypeScript pour tous les types d'événements
30
+ - **Async**: Les handlers asynchrones ne bloquent pas l'exécution
31
+ - **Extensible**: Facile d'ajouter des événements personnalisés
32
+ - **Non-bloquant**: L'exécution continue même si les handlers échouent
33
+ - **Zero runtime deps**: Implémentation pure TypeScript
34
+
35
+ ## Types d'Événements
36
+
37
+ ### Événements de Workflow
38
+
39
+ ```typescript
40
+ // Démarrage de workflow
41
+ interface WorkflowStartEvent {
42
+ type: 'workflow:start';
43
+ workflowId: string;
44
+ workflowName: string;
45
+ input: string;
46
+ agentCount: number;
47
+ timestamp: number;
48
+ correlationId?: string;
49
+ }
50
+
51
+ // Complétion de workflow
52
+ interface WorkflowCompleteEvent {
53
+ type: 'workflow:complete';
54
+ workflowId: string;
55
+ workflowName: string;
56
+ result: WorkflowResult;
57
+ duration: number;
58
+ timestamp: number;
59
+ }
60
+
61
+ // Erreur de workflow
62
+ interface WorkflowErrorEvent {
63
+ type: 'workflow:error';
64
+ workflowId: string;
65
+ workflowName: string;
66
+ error: Error;
67
+ timestamp: number;
68
+ }
69
+ ```
70
+
71
+ ### Événements de Step
72
+
73
+ ```typescript
74
+ // Démarrage de step
75
+ interface StepStartEvent {
76
+ type: 'step:start';
77
+ stepId: string;
78
+ stepName: string;
79
+ agentIds: string[];
80
+ executionType: string;
81
+ timestamp: number;
82
+ }
83
+
84
+ // Complétion de step
85
+ interface StepCompleteEvent {
86
+ type: 'step:complete';
87
+ stepId: string;
88
+ stepName: string;
89
+ results: StepResult[];
90
+ duration: number;
91
+ timestamp: number;
92
+ }
93
+
94
+ // Erreur de step
95
+ interface StepErrorEvent {
96
+ type: 'step:error';
97
+ stepId: string;
98
+ stepName: string;
99
+ error: Error;
100
+ timestamp: number;
101
+ }
102
+
103
+ // Step sauté
104
+ interface StepSkippedEvent {
105
+ type: 'step:skipped';
106
+ stepId: string;
107
+ stepName: string;
108
+ reason: string;
109
+ timestamp: number;
110
+ }
111
+ ```
112
+
113
+ ### Événements d'Agent
114
+
115
+ ```typescript
116
+ // Démarrage d'agent
117
+ interface AgentStartEvent {
118
+ type: 'agent:start';
119
+ agentId: string;
120
+ agentName?: string;
121
+ modelName: string;
122
+ prompt: unknown;
123
+ timestamp: number;
124
+ }
125
+
126
+ // Complétion d'agent
127
+ interface AgentCompleteEvent {
128
+ type: 'agent:complete';
129
+ agentId: string;
130
+ agentName?: string;
131
+ modelName: string;
132
+ result: string;
133
+ duration: number;
134
+ timestamp: number;
135
+ }
136
+
137
+ // Erreur d'agent
138
+ interface AgentErrorEvent {
139
+ type: 'agent:error';
140
+ agentId: string;
141
+ agentName?: string;
142
+ modelName: string;
143
+ error: Error;
144
+ timestamp: number;
145
+ }
146
+
147
+ // Retry d'agent
148
+ interface AgentRetryEvent {
149
+ type: 'agent:retry';
150
+ agentId: string;
151
+ agentName?: string;
152
+ attempt: number;
153
+ maxAttempts: number;
154
+ error: Error;
155
+ timestamp: number;
156
+ }
157
+ ```
158
+
159
+ ### Événements de Progression
160
+
161
+ ```typescript
162
+ interface ProgressEvent {
163
+ type: 'progress';
164
+ percent: number; // 0-100
165
+ phase: string; // Description de la phase
166
+ estimatedTimeRemaining?: number; // ms
167
+ details?: Record<string, unknown>;
168
+ timestamp: number;
169
+ }
170
+ ```
171
+
172
+ ### Événements de Message
173
+
174
+ ```typescript
175
+ // Message envoyé
176
+ interface MessageSentEvent {
177
+ type: 'message:sent';
178
+ from: string;
179
+ to: string | 'broadcast';
180
+ messageType: string;
181
+ content: string;
182
+ timestamp: number;
183
+ }
184
+
185
+ // Message reçu
186
+ interface MessageReceivedEvent {
187
+ type: 'message:received';
188
+ from: string;
189
+ to: string;
190
+ messageType: string;
191
+ content: string;
192
+ timestamp: number;
193
+ }
194
+ ```
195
+
196
+ ### Événements de Debug
197
+
198
+ ```typescript
199
+ interface DebugEvent {
200
+ type: 'debug';
201
+ level: 'trace' | 'debug' | 'info' | 'warn' | 'error';
202
+ message: string;
203
+ data?: unknown;
204
+ timestamp: number;
205
+ }
206
+ ```
207
+
208
+ ### Événements Personnalisés
209
+
210
+ ```typescript
211
+ interface CustomEvent {
212
+ type: 'custom';
213
+ name: string;
214
+ data: unknown;
215
+ timestamp: number;
216
+ }
217
+ ```
218
+
219
+ ## Event Emitter
220
+
221
+ ### Création et Utilisation de Base
222
+
223
+ ```typescript
224
+ import { SocietyEventEmitter } from 'societyai';
225
+
226
+ const emitter = new SocietyEventEmitter();
227
+
228
+ // Écouter des événements
229
+ emitter.on('workflow:start', (event) => {
230
+ console.log(`Workflow started: ${event.workflowName}`);
231
+ });
232
+
233
+ emitter.on('agent:complete', (event) => {
234
+ console.log(`Agent ${event.agentId} completed in ${event.duration}ms`);
235
+ });
236
+
237
+ // Handlers asynchrones
238
+ emitter.on('workflow:complete', async (event) => {
239
+ await saveResults(event.result);
240
+ await notifyUser(event.workflowId);
241
+ });
242
+
243
+ // Émission d'événements
244
+ emitter.emit({
245
+ type: 'workflow:start',
246
+ workflowId: 'wf-123',
247
+ workflowName: 'Analysis',
248
+ input: 'Analyze this',
249
+ agentCount: 3,
250
+ timestamp: Date.now(),
251
+ });
252
+ ```
253
+
254
+ ### Wildcard et Événements Multiples
255
+
256
+ ```typescript
257
+ // Écouter tous les événements
258
+ emitter.on('*', (event) => {
259
+ console.log(`Event: ${event.type}`);
260
+ });
261
+
262
+ // Écouter plusieurs types
263
+ emitter.on('workflow:start', handleWorkflowStart);
264
+ emitter.on('workflow:complete', handleWorkflowComplete);
265
+ emitter.on('workflow:error', handleWorkflowError);
266
+ ```
267
+
268
+ ### Once - Écouter une seule fois
269
+
270
+ ```typescript
271
+ // S'exécute une seule fois puis se détache
272
+ emitter.once('workflow:complete', (event) => {
273
+ console.log('First workflow completed!');
274
+ });
275
+ ```
276
+
277
+ ### Détachement des Handlers
278
+
279
+ ```typescript
280
+ const handler = (event) => console.log(event);
281
+
282
+ emitter.on('agent:start', handler);
283
+
284
+ // Détacher plus tard
285
+ emitter.off('agent:start', handler);
286
+
287
+ // Détacher tous les handlers d'un type
288
+ emitter.removeAllListeners('agent:start');
289
+
290
+ // Détacher tous les handlers
291
+ emitter.removeAllListeners();
292
+ ```
293
+
294
+ ## Event Handlers
295
+
296
+ ### Handler Type-Safe
297
+
298
+ ```typescript
299
+ import { EventHandler } from 'societyai';
300
+
301
+ // Handler typé pour un type d'événement spécifique
302
+ const workflowHandler: EventHandler<WorkflowCompleteEvent> = (event) => {
303
+ // 'event' est correctement typé comme WorkflowCompleteEvent
304
+ console.log(event.result.output);
305
+ console.log(event.duration);
306
+ };
307
+
308
+ emitter.on('workflow:complete', workflowHandler);
309
+ ```
310
+
311
+ ### Handler avec Gestion d'Erreur
312
+
313
+ ```typescript
314
+ emitter.on('agent:error', (event) => {
315
+ console.error(`Agent ${event.agentId} failed:`, event.error);
316
+
317
+ // Notification
318
+ notifyDevelopers({
319
+ agentId: event.agentId,
320
+ error: event.error.message,
321
+ timestamp: event.timestamp,
322
+ });
323
+
324
+ // Logging
325
+ logger.error('Agent execution failed', {
326
+ agentId: event.agentId,
327
+ model: event.modelName,
328
+ error: event.error,
329
+ });
330
+ });
331
+ ```
332
+
333
+ ### Handler Conditionnel
334
+
335
+ ```typescript
336
+ emitter.on('agent:complete', (event) => {
337
+ // Seulement pour certains agents
338
+ if (event.agentId.startsWith('critical-')) {
339
+ // Action spéciale
340
+ priorityLog(event);
341
+ }
342
+
343
+ // Seulement si lent
344
+ if (event.duration > 5000) {
345
+ console.warn(`Slow agent: ${event.agentId} took ${event.duration}ms`);
346
+ }
347
+ });
348
+ ```
349
+
350
+ ## Progress Tracking
351
+
352
+ ### ProgressTracker
353
+
354
+ ```typescript
355
+ import { ProgressTracker } from 'societyai';
356
+
357
+ const tracker = new ProgressTracker(emitter);
358
+
359
+ // Démarrer le tracking
360
+ tracker.start('workflow-123', {
361
+ totalSteps: 5,
362
+ estimatedDuration: 30000, // 30s
363
+ });
364
+
365
+ // Mettre à jour la progression
366
+ tracker.updateProgress('workflow-123', {
367
+ current: 1,
368
+ phase: 'Analyzing input',
369
+ details: { agentsActive: 2 },
370
+ });
371
+
372
+ tracker.updateProgress('workflow-123', {
373
+ current: 2,
374
+ phase: 'Processing data',
375
+ });
376
+
377
+ // Compléter
378
+ tracker.complete('workflow-123');
379
+
380
+ // Les événements 'progress' sont automatiquement émis
381
+ ```
382
+
383
+ ### Tracking Manuel
384
+
385
+ ```typescript
386
+ // Émettre manuellement des événements de progression
387
+ emitter.emit({
388
+ type: 'progress',
389
+ percent: 25,
390
+ phase: 'Step 1 of 4',
391
+ estimatedTimeRemaining: 15000,
392
+ timestamp: Date.now(),
393
+ });
394
+
395
+ // Avec détails
396
+ emitter.emit({
397
+ type: 'progress',
398
+ percent: 50,
399
+ phase: 'Processing',
400
+ details: {
401
+ itemsProcessed: 50,
402
+ itemsTotal: 100,
403
+ currentItem: 'item-50',
404
+ },
405
+ timestamp: Date.now(),
406
+ });
407
+ ```
408
+
409
+ ### Progress UI
410
+
411
+ ```typescript
412
+ // Intégration avec une barre de progression
413
+ emitter.on('progress', (event) => {
414
+ updateProgressBar(event.percent);
415
+ updateStatusText(event.phase);
416
+
417
+ if (event.estimatedTimeRemaining) {
418
+ updateETA(event.estimatedTimeRemaining);
419
+ }
420
+ });
421
+
422
+ // Console progress bar
423
+ emitter.on('progress', (event) => {
424
+ const bar = '='.repeat(event.percent / 2) + ' '.repeat(50 - event.percent / 2);
425
+ process.stdout.write(`\r[${bar}] ${event.percent}% - ${event.phase}`);
426
+ });
427
+ ```
428
+
429
+ ## Event Filtering
430
+
431
+ ### FilteredEventEmitter
432
+
433
+ ```typescript
434
+ import { FilteredEventEmitter } from 'societyai';
435
+
436
+ const baseEmitter = new SocietyEventEmitter();
437
+
438
+ // Créer un emitter filtré
439
+ const filteredEmitter = new FilteredEventEmitter(baseEmitter, (event) => {
440
+ // Filtrer seulement les événements d'agents spécifiques
441
+ if (event.type.startsWith('agent:')) {
442
+ const agentEvent = event as AgentStartEvent;
443
+ return agentEvent.agentId.startsWith('production-');
444
+ }
445
+ return true;
446
+ });
447
+
448
+ // Seulement les événements filtrés passent
449
+ filteredEmitter.on('agent:start', (event) => {
450
+ // Seulement les agents de production
451
+ });
452
+ ```
453
+
454
+ ### Filtres par Type
455
+
456
+ ```typescript
457
+ // Créer des emitters spécialisés
458
+ const workflowEmitter = new FilteredEventEmitter(baseEmitter, (event) =>
459
+ event.type.startsWith('workflow:')
460
+ );
461
+
462
+ const agentEmitter = new FilteredEventEmitter(baseEmitter, (event) =>
463
+ event.type.startsWith('agent:')
464
+ );
465
+
466
+ // Chacun reçoit seulement son type d'événements
467
+ workflowEmitter.on('workflow:start', handleWorkflowStart);
468
+ agentEmitter.on('agent:complete', handleAgentComplete);
469
+ ```
470
+
471
+ ### Filtres Complexes
472
+
473
+ ```typescript
474
+ const criticalEmitter = new FilteredEventEmitter(baseEmitter, (event) => {
475
+ // Seulement les erreurs
476
+ if (event.type.includes('error')) return true;
477
+
478
+ // Agents lents
479
+ if (event.type === 'agent:complete') {
480
+ const agentEvent = event as AgentCompleteEvent;
481
+ return agentEvent.duration > 10000;
482
+ }
483
+
484
+ // Workflows échoués
485
+ if (event.type === 'workflow:complete') {
486
+ const wfEvent = event as WorkflowCompleteEvent;
487
+ return !wfEvent.result.success;
488
+ }
489
+
490
+ return false;
491
+ });
492
+
493
+ // Monitoring critique seulement
494
+ criticalEmitter.on('*', (event) => {
495
+ alertOpsTeam(event);
496
+ });
497
+ ```
498
+
499
+ ## Event History
500
+
501
+ ### Activer l'Historique
502
+
503
+ ```typescript
504
+ const emitter = new SocietyEventEmitter();
505
+
506
+ // Activer avec taille max
507
+ emitter.enableHistory(1000); // Garde 1000 derniers événements
508
+
509
+ // Désactiver
510
+ emitter.disableHistory();
511
+ ```
512
+
513
+ ### Accéder à l'Historique
514
+
515
+ ```typescript
516
+ // Tous les événements
517
+ const allEvents = emitter.getHistory();
518
+
519
+ // Filtrer par type
520
+ const workflowEvents = emitter.getHistoryByType('workflow:start');
521
+
522
+ // Filtrer par temps
523
+ const recentEvents = emitter.getHistorySince(Date.now() - 60000); // 1 minute
524
+
525
+ // Événements entre deux timestamps
526
+ const events = emitter.getHistoryBetween(startTime, endTime);
527
+ ```
528
+
529
+ ### Replay des Événements
530
+
531
+ ```typescript
532
+ const history = emitter.getHistory();
533
+
534
+ // Replay dans un nouvel emitter
535
+ const replayEmitter = new SocietyEventEmitter();
536
+ replayEmitter.on('*', logEvent);
537
+
538
+ for (const event of history) {
539
+ replayEmitter.emit(event);
540
+ }
541
+ ```
542
+
543
+ ### Clear History
544
+
545
+ ```typescript
546
+ // Vider l'historique
547
+ emitter.clearHistory();
548
+ ```
549
+
550
+ ## Intégrations
551
+
552
+ ### Event Logger
553
+
554
+ ```typescript
555
+ import { EventLogger } from 'societyai';
556
+
557
+ const logger = new EventLogger(emitter, {
558
+ logToConsole: true,
559
+ logToFile: './logs/events.log',
560
+ includeTypes: ['workflow:*', 'agent:error'],
561
+ excludeTypes: ['debug'],
562
+ formatter: (event) => {
563
+ return `[${new Date(event.timestamp).toISOString()}] ${event.type}`;
564
+ },
565
+ });
566
+
567
+ // Les événements sont automatiquement loggés
568
+ ```
569
+
570
+ ### Event Aggregator
571
+
572
+ ```typescript
573
+ import { EventAggregator } from 'societyai';
574
+
575
+ const aggregator = new EventAggregator(emitter);
576
+
577
+ // Agréger sur une période
578
+ aggregator.startAggregation({
579
+ windowSize: 60000, // 1 minute
580
+ onAggregated: (summary) => {
581
+ console.log('Events in last minute:', summary.total);
582
+ console.log('By type:', summary.byType);
583
+ console.log('Errors:', summary.errors);
584
+ },
585
+ });
586
+
587
+ // Récupérer le résumé
588
+ const summary = aggregator.getSummary();
589
+ console.log(`Total workflows: ${summary.workflows}`);
590
+ console.log(`Total agents: ${summary.agents}`);
591
+ console.log(`Average duration: ${summary.avgDuration}ms`);
592
+ ```
593
+
594
+ ### Intégration avec Society
595
+
596
+ ```typescript
597
+ import { Society, createEventEmitter } from 'societyai';
598
+
599
+ const emitter = createEventEmitter();
600
+
601
+ // Logger tous les événements
602
+ emitter.on('*', (event) => {
603
+ console.log(`[${event.type}]`, event);
604
+ });
605
+
606
+ // Tracker la progression
607
+ emitter.on('progress', (event) => {
608
+ updateUI(event.percent, event.phase);
609
+ });
610
+
611
+ // Utiliser avec Society
612
+ const result = await Society.create()
613
+ .withName('Event-Tracked Society')
614
+ .withEvents(emitter) // Attacher l'emitter
615
+ .addAgent(/* ... */)
616
+ .execute(input);
617
+ ```
618
+
619
+ ## Exemples Complets
620
+
621
+ ### Exemple 1: Monitoring Complet
622
+
623
+ ```typescript
624
+ import { SocietyEventEmitter, ProgressTracker, EventLogger, Society } from 'societyai';
625
+
626
+ // Configuration du monitoring
627
+ const emitter = new SocietyEventEmitter().enableHistory(500);
628
+
629
+ const tracker = new ProgressTracker(emitter);
630
+ const logger = new EventLogger(emitter, {
631
+ logToFile: './logs/workflow.log',
632
+ });
633
+
634
+ // Métriques
635
+ const metrics = {
636
+ workflows: 0,
637
+ agents: 0,
638
+ errors: 0,
639
+ totalDuration: 0,
640
+ };
641
+
642
+ emitter.on('workflow:start', (event) => {
643
+ metrics.workflows++;
644
+ console.log(`📊 Starting workflow: ${event.workflowName}`);
645
+ tracker.start(event.workflowId, {
646
+ totalSteps: event.agentCount,
647
+ });
648
+ });
649
+
650
+ emitter.on('agent:start', (event) => {
651
+ metrics.agents++;
652
+ console.log(`🤖 Agent ${event.agentId} processing...`);
653
+ });
654
+
655
+ emitter.on('agent:complete', (event) => {
656
+ console.log(`✅ Agent ${event.agentId} done in ${event.duration}ms`);
657
+ tracker.updateProgress(event.agentId, {
658
+ current: metrics.agents,
659
+ phase: `Agent ${event.agentId} completed`,
660
+ });
661
+ });
662
+
663
+ emitter.on('agent:error', (event) => {
664
+ metrics.errors++;
665
+ console.error(`❌ Agent ${event.agentId} failed:`, event.error);
666
+ });
667
+
668
+ emitter.on('workflow:complete', (event) => {
669
+ metrics.totalDuration += event.duration;
670
+ const avgDuration = metrics.totalDuration / metrics.workflows;
671
+
672
+ console.log(`
673
+ 🎉 Workflow Complete!
674
+ Duration: ${event.duration}ms
675
+ Success: ${event.result.success}
676
+ Average: ${avgDuration.toFixed(0)}ms
677
+ Total Agents: ${metrics.agents}
678
+ Errors: ${metrics.errors}
679
+ `);
680
+
681
+ tracker.complete(event.workflowId);
682
+ });
683
+
684
+ // Utiliser avec Society
685
+ const result = await Society.create()
686
+ .withName('Monitored Workflow')
687
+ .withEvents(emitter)
688
+ .addAgent(/* ... */)
689
+ .execute(input);
690
+ ```
691
+
692
+ ### Exemple 2: Dashboard en Temps Réel
693
+
694
+ ```typescript
695
+ interface DashboardState {
696
+ activeWorkflows: Map<string, WorkflowInfo>;
697
+ completedWorkflows: number;
698
+ failedWorkflows: number;
699
+ activeAgents: Set<string>;
700
+ lastEvents: SocietyEvent[];
701
+ }
702
+
703
+ class WorkflowDashboard {
704
+ private state: DashboardState = {
705
+ activeWorkflows: new Map(),
706
+ completedWorkflows: 0,
707
+ failedWorkflows: 0,
708
+ activeAgents: new Set(),
709
+ lastEvents: [],
710
+ };
711
+
712
+ constructor(private emitter: SocietyEventEmitter) {
713
+ this.setupListeners();
714
+ }
715
+
716
+ private setupListeners() {
717
+ this.emitter.on('workflow:start', (event) => {
718
+ this.state.activeWorkflows.set(event.workflowId, {
719
+ id: event.workflowId,
720
+ name: event.workflowName,
721
+ startTime: event.timestamp,
722
+ agentCount: event.agentCount,
723
+ completedAgents: 0,
724
+ });
725
+ this.update();
726
+ });
727
+
728
+ this.emitter.on('agent:start', (event) => {
729
+ this.state.activeAgents.add(event.agentId);
730
+ this.update();
731
+ });
732
+
733
+ this.emitter.on('agent:complete', (event) => {
734
+ this.state.activeAgents.delete(event.agentId);
735
+
736
+ // Mettre à jour le workflow
737
+ for (const workflow of this.state.activeWorkflows.values()) {
738
+ workflow.completedAgents++;
739
+ }
740
+ this.update();
741
+ });
742
+
743
+ this.emitter.on('workflow:complete', (event) => {
744
+ this.state.activeWorkflows.delete(event.workflowId);
745
+ if (event.result.success) {
746
+ this.state.completedWorkflows++;
747
+ } else {
748
+ this.state.failedWorkflows++;
749
+ }
750
+ this.update();
751
+ });
752
+
753
+ this.emitter.on('*', (event) => {
754
+ this.state.lastEvents.unshift(event);
755
+ if (this.state.lastEvents.length > 10) {
756
+ this.state.lastEvents.pop();
757
+ }
758
+ });
759
+ }
760
+
761
+ private update() {
762
+ // Rafraîchir l'UI
763
+ console.clear();
764
+ console.log('╔══════════════════════════════════════╗');
765
+ console.log('║ SocietyAI Workflow Dashboard ║');
766
+ console.log('╠══════════════════════════════════════╣');
767
+ console.log(`║ Active Workflows: ${this.state.activeWorkflows.size} ║`);
768
+ console.log(`║ Completed: ${this.state.completedWorkflows} ║`);
769
+ console.log(`║ Failed: ${this.state.failedWorkflows} ║`);
770
+ console.log(`║ Active Agents: ${this.state.activeAgents.size} ║`);
771
+ console.log('╠══════════════════════════════════════╣');
772
+
773
+ for (const workflow of this.state.activeWorkflows.values()) {
774
+ const progress = (workflow.completedAgents / workflow.agentCount) * 100;
775
+ const bar = '█'.repeat(progress / 5) + '░'.repeat(20 - progress / 5);
776
+ console.log(`║ ${workflow.name.padEnd(20)} [${bar}] ${progress.toFixed(0)}%`);
777
+ }
778
+
779
+ console.log('╚══════════════════════════════════════╝');
780
+ }
781
+
782
+ getState(): DashboardState {
783
+ return this.state;
784
+ }
785
+ }
786
+
787
+ // Utilisation
788
+ const emitter = new SocietyEventEmitter();
789
+ const dashboard = new WorkflowDashboard(emitter);
790
+
791
+ // Exécuter workflows...
792
+ ```
793
+
794
+ ### Exemple 3: Testing avec Event Assertions
795
+
796
+ ```typescript
797
+ describe('Workflow Events', () => {
798
+ let emitter: SocietyEventEmitter;
799
+ let events: SocietyEvent[];
800
+
801
+ beforeEach(() => {
802
+ emitter = new SocietyEventEmitter().enableHistory();
803
+ events = [];
804
+
805
+ emitter.on('*', (event) => {
806
+ events.push(event);
807
+ });
808
+ });
809
+
810
+ it('should emit workflow lifecycle events', async () => {
811
+ await Society.create().withEvents(emitter).addAgent(/* ... */).execute('test input');
812
+
813
+ // Vérifier l'ordre des événements
814
+ expect(events[0].type).toBe('workflow:start');
815
+ expect(events[events.length - 1].type).toBe('workflow:complete');
816
+
817
+ // Vérifier qu'on a des événements d'agents
818
+ const agentEvents = events.filter((e) => e.type.startsWith('agent:'));
819
+ expect(agentEvents.length).toBeGreaterThan(0);
820
+ });
821
+
822
+ it('should emit error events on failure', async () => {
823
+ // Agent qui échoue
824
+ const failingModel = {
825
+ name: () => 'FailingModel',
826
+ process: async () => {
827
+ throw new Error('Test error');
828
+ },
829
+ supportsPromptType: () => true,
830
+ };
831
+
832
+ try {
833
+ await Society.create()
834
+ .withEvents(emitter)
835
+ .addAgent((a) =>
836
+ a
837
+ .withId('failing')
838
+ .withRole((r) => r.withSystemPrompt('test'))
839
+ .withModel(failingModel)
840
+ )
841
+ .execute('test');
842
+ } catch (e) {
843
+ // Expected
844
+ }
845
+
846
+ const errorEvents = events.filter((e) => e.type.includes('error'));
847
+ expect(errorEvents.length).toBeGreaterThan(0);
848
+ });
849
+ });
850
+ ```
851
+
852
+ ### Exemple 4: Audit Trail
853
+
854
+ ```typescript
855
+ class AuditTrail {
856
+ private db: Database;
857
+
858
+ constructor(private emitter: SocietyEventEmitter) {
859
+ this.setupAuditLogging();
860
+ }
861
+
862
+ private setupAuditLogging() {
863
+ // Logger tous les événements importants
864
+ const auditEvents = [
865
+ 'workflow:start',
866
+ 'workflow:complete',
867
+ 'workflow:error',
868
+ 'agent:start',
869
+ 'agent:complete',
870
+ 'agent:error',
871
+ ];
872
+
873
+ for (const eventType of auditEvents) {
874
+ this.emitter.on(eventType as any, async (event) => {
875
+ await this.logToDatabase(event);
876
+ });
877
+ }
878
+ }
879
+
880
+ private async logToDatabase(event: SocietyEvent) {
881
+ await this.db.auditLogs.insert({
882
+ eventType: event.type,
883
+ timestamp: event.timestamp,
884
+ correlationId: event.correlationId,
885
+ data: JSON.stringify(event),
886
+ userId: getCurrentUser()?.id,
887
+ sessionId: getCurrentSession()?.id,
888
+ });
889
+ }
890
+
891
+ async getAuditLog(workflowId: string): Promise<AuditLog[]> {
892
+ return await this.db.auditLogs
893
+ .query()
894
+ .where('correlationId', workflowId)
895
+ .orderBy('timestamp', 'asc')
896
+ .all();
897
+ }
898
+
899
+ async searchAudit(criteria: AuditSearchCriteria): Promise<AuditLog[]> {
900
+ let query = this.db.auditLogs.query();
901
+
902
+ if (criteria.eventType) {
903
+ query = query.where('eventType', criteria.eventType);
904
+ }
905
+
906
+ if (criteria.dateRange) {
907
+ query = query
908
+ .where('timestamp', '>=', criteria.dateRange.start)
909
+ .where('timestamp', '<=', criteria.dateRange.end);
910
+ }
911
+
912
+ if (criteria.userId) {
913
+ query = query.where('userId', criteria.userId);
914
+ }
915
+
916
+ return await query.all();
917
+ }
918
+ }
919
+ ```
920
+
921
+ ## Bonnes Pratiques
922
+
923
+ ### 1. Gestion des Erreurs dans les Handlers
924
+
925
+ ```typescript
926
+ // ✅ Bon - handler avec try-catch
927
+ emitter.on('workflow:complete', async (event) => {
928
+ try {
929
+ await saveResults(event.result);
930
+ } catch (error) {
931
+ console.error('Failed to save results:', error);
932
+ // Ne pas propager l'erreur
933
+ }
934
+ });
935
+
936
+ // ❌ Mauvais - erreurs non gérées
937
+ emitter.on('workflow:complete', async (event) => {
938
+ await saveResults(event.result); // Peut throw
939
+ });
940
+ ```
941
+
942
+ ### 2. Nettoyage des Listeners
943
+
944
+ ```typescript
945
+ // ✅ Bon - détacher quand fini
946
+ class WorkflowMonitor {
947
+ private handler: EventHandler<WorkflowCompleteEvent>;
948
+
949
+ start(emitter: SocietyEventEmitter) {
950
+ this.handler = (event) => this.handle(event);
951
+ emitter.on('workflow:complete', this.handler);
952
+ }
953
+
954
+ stop(emitter: SocietyEventEmitter) {
955
+ emitter.off('workflow:complete', this.handler);
956
+ }
957
+ }
958
+ ```
959
+
960
+ ### 3. Corrélation des Événements
961
+
962
+ ```typescript
963
+ // ✅ Bon - utiliser correlationId
964
+ const correlationId = generateId();
965
+
966
+ emitter.setCorrelationId(correlationId);
967
+
968
+ // Tous les événements auront le même correlationId
969
+ await workflow.execute(input);
970
+
971
+ // Récupérer tous les événements liés
972
+ const related = emitter.getHistory().filter((e) => e.correlationId === correlationId);
973
+ ```
974
+
975
+ ### 4. Performance
976
+
977
+ ```typescript
978
+ // ✅ Bon - handlers légers
979
+ emitter.on('progress', (event) => {
980
+ // Rapide
981
+ progressBar.update(event.percent);
982
+ });
983
+
984
+ // ❌ Mauvais - handlers lourds
985
+ emitter.on('progress', async (event) => {
986
+ // Lent - bloque l'émission
987
+ await heavyDatabaseOperation(event);
988
+ });
989
+
990
+ // ✅ Mieux - async mais non-bloquant
991
+ emitter.on('progress', (event) => {
992
+ // Fire and forget
993
+ heavyDatabaseOperation(event).catch(console.error);
994
+ });
995
+ ```
996
+
997
+ ## API Reference
998
+
999
+ ### `SocietyEventEmitter`
1000
+
1001
+ **Méthodes:**
1002
+
1003
+ - `on<K>(type: K, handler: EventHandler<T>): this` - Écouter un événement
1004
+ - `once<K>(type: K, handler: EventHandler<T>): this` - Écouter une fois
1005
+ - `off<K>(type: K, handler: EventHandler<T>): this` - Détacher un handler
1006
+ - `emit(event: SocietyEvent): void` - Émettre un événement
1007
+ - `enableHistory(maxSize?: number): this` - Activer l'historique
1008
+ - `disableHistory(): this` - Désactiver l'historique
1009
+ - `getHistory(): SocietyEvent[]` - Récupérer l'historique
1010
+ - `clearHistory(): void` - Vider l'historique
1011
+ - `removeAllListeners(type?: string): this` - Détacher tous les handlers
1012
+
1013
+ ### `ProgressTracker`
1014
+
1015
+ **Méthodes:**
1016
+
1017
+ - `start(id: string, config: ProgressConfig): void` - Démarrer le tracking
1018
+ - `updateProgress(id: string, update: ProgressUpdate): void` - Mettre à jour
1019
+ - `complete(id: string): void` - Compléter
1020
+ - `fail(id: string, error: Error): void` - Marquer comme échoué
1021
+
1022
+ ### `FilteredEventEmitter`
1023
+
1024
+ **Constructeur:**
1025
+
1026
+ - `new FilteredEventEmitter(source: SocietyEventEmitter, filter: EventFilter<SocietyEvent>)`
1027
+
1028
+ ### `EventLogger`
1029
+
1030
+ **Constructeur:**
1031
+
1032
+ - `new EventLogger(emitter: SocietyEventEmitter, options: EventLoggerOptions)`
1033
+
1034
+ ### `EventAggregator`
1035
+
1036
+ **Méthodes:**
1037
+
1038
+ - `startAggregation(config: AggregationConfig): void` - Démarrer l'agrégation
1039
+ - `stopAggregation(): void` - Arrêter
1040
+ - `getSummary(): EventSummary` - Récupérer le résumé
1041
+
1042
+ ## Voir Aussi
1043
+
1044
+ - [Architecture](./architecture.md) - Concepts de base
1045
+ - [Workflows](./workflows.md) - Intégration avec les workflows
1046
+ - [Metrics & Observability](./metrics-observability.md) - Métriques et monitoring
1047
+ - [Advanced Features](./advanced.md) - Fonctionnalités avancées