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.
- package/CHANGELOG.md +111 -0
- package/LICENSE +21 -0
- package/README.md +879 -0
- package/dist/builder.d.ts +181 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +667 -0
- package/dist/builder.js.map +1 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +11 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +107 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +319 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +85 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +219 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +395 -0
- package/dist/events.js.map +1 -0
- package/dist/graph.d.ts +104 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +366 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +113 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +13 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +78 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory.d.ts +146 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +353 -0
- package/dist/memory.js.map +1 -0
- package/dist/metrics.d.ts +143 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +271 -0
- package/dist/metrics.js.map +1 -0
- package/dist/middleware.d.ts +147 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +484 -0
- package/dist/middleware.js.map +1 -0
- package/dist/models.d.ts +32 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +211 -0
- package/dist/models.js.map +1 -0
- package/dist/patterns.d.ts +6 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +68 -0
- package/dist/patterns.js.map +1 -0
- package/dist/pipeline.d.ts +84 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +569 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/retry.d.ts +5 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +70 -0
- package/dist/retry.js.map +1 -0
- package/dist/society.d.ts +94 -0
- package/dist/society.d.ts.map +1 -0
- package/dist/society.js +721 -0
- package/dist/society.js.map +1 -0
- package/dist/strategies.d.ts +55 -0
- package/dist/strategies.d.ts.map +1 -0
- package/dist/strategies.js +678 -0
- package/dist/strategies.js.map +1 -0
- package/dist/tools.d.ts +88 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +366 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +213 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +64 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +334 -0
- package/dist/validation.js.map +1 -0
- package/dist/worker-pool.d.ts +17 -0
- package/dist/worker-pool.d.ts.map +1 -0
- package/dist/worker-pool.js +80 -0
- package/dist/worker-pool.js.map +1 -0
- package/docs/README.md +468 -0
- package/docs/advanced.md +616 -0
- package/docs/aggregation-strategies.md +926 -0
- package/docs/api-reference.md +771 -0
- package/docs/architecture.md +648 -0
- package/docs/context-system.md +642 -0
- package/docs/event-system.md +1047 -0
- package/docs/examples.md +576 -0
- package/docs/getting-started.md +564 -0
- package/docs/graph-execution.md +389 -0
- package/docs/memory-system.md +497 -0
- package/docs/metrics-observability.md +560 -0
- package/docs/middleware-system.md +1038 -0
- package/docs/migration.md +296 -0
- package/docs/pipeline-patterns.md +761 -0
- package/docs/structured-output.md +612 -0
- package/docs/tool-calling.md +491 -0
- package/docs/workflows.md +740 -0
- package/examples/README.md +234 -0
- package/examples/advanced-patterns.ts +115 -0
- package/examples/complete-integration.ts +327 -0
- package/examples/graph-workflow.ts +161 -0
- package/examples/memory-system.ts +155 -0
- package/examples/metrics-tracking.ts +243 -0
- package/examples/structured-output.ts +231 -0
- package/examples/tool-calling.ts +163 -0
- package/package.json +94 -0
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
# Context System
|
|
2
|
+
|
|
3
|
+
Le système de contexte de SocietyAI fournit un mécanisme d'injection de dépendances type-safe pour partager l'état entre les agents sans couplage fort.
|
|
4
|
+
|
|
5
|
+
## Table des Matières
|
|
6
|
+
|
|
7
|
+
- [Vue d'ensemble](#vue-densemble)
|
|
8
|
+
- [Context Tokens](#context-tokens)
|
|
9
|
+
- [Context Provider](#context-provider)
|
|
10
|
+
- [Context Scopes](#context-scopes)
|
|
11
|
+
- [Utilisation avec des Agents](#utilisation-avec-des-agents)
|
|
12
|
+
- [Patterns Avancés](#patterns-avancés)
|
|
13
|
+
- [Exemples Complets](#exemples-complets)
|
|
14
|
+
|
|
15
|
+
## Vue d'ensemble
|
|
16
|
+
|
|
17
|
+
Le système de contexte permet de:
|
|
18
|
+
|
|
19
|
+
- **Injection de dépendances type-safe** avec des tokens typés
|
|
20
|
+
- **Partage d'état** entre agents sans référence directe
|
|
21
|
+
- **Scopes hiérarchiques** (global, workflow, step, agent)
|
|
22
|
+
- **Lazy initialization** avec des factories
|
|
23
|
+
- **Héritage de contexte** avec des providers enfants
|
|
24
|
+
- **Immutabilité par défaut** avec option mutable
|
|
25
|
+
|
|
26
|
+
### Principes de Design
|
|
27
|
+
|
|
28
|
+
- **Type-safe**: Support complet des génériques TypeScript
|
|
29
|
+
- **Zero coupling**: Les agents ne dépendent pas les uns des autres
|
|
30
|
+
- **Composable**: Les contextes peuvent être imbriqués et combinés
|
|
31
|
+
- **Zero runtime deps**: Implémentation pure TypeScript
|
|
32
|
+
|
|
33
|
+
## Context Tokens
|
|
34
|
+
|
|
35
|
+
Les tokens de contexte sont des clés type-safe pour accéder aux valeurs de contexte.
|
|
36
|
+
|
|
37
|
+
### Création de Tokens
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { createContextToken } from 'societyai';
|
|
41
|
+
|
|
42
|
+
// Token simple
|
|
43
|
+
const UserContext = createContextToken<User>('user');
|
|
44
|
+
|
|
45
|
+
// Token avec valeur par défaut
|
|
46
|
+
const ConfigContext = createContextToken<Config>('config', {
|
|
47
|
+
apiUrl: 'https://api.example.com',
|
|
48
|
+
timeout: 5000,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Token pour des données primitives
|
|
52
|
+
const ApiKeyContext = createContextToken<string>('apiKey');
|
|
53
|
+
|
|
54
|
+
// Token pour des structures complexes
|
|
55
|
+
interface AppState {
|
|
56
|
+
users: User[];
|
|
57
|
+
session: Session;
|
|
58
|
+
settings: Settings;
|
|
59
|
+
}
|
|
60
|
+
const AppStateContext = createContextToken<AppState>('appState');
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Vérification de Tokens
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { isContextToken } from 'societyai';
|
|
67
|
+
|
|
68
|
+
const token = createContextToken<string>('test');
|
|
69
|
+
console.log(isContextToken(token)); // true
|
|
70
|
+
console.log(isContextToken('test')); // false
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Context Provider
|
|
74
|
+
|
|
75
|
+
Le `ContextProvider` gère les valeurs de contexte et permet l'injection.
|
|
76
|
+
|
|
77
|
+
### Création de Base
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { ContextProvider } from 'societyai';
|
|
81
|
+
|
|
82
|
+
const provider = ContextProvider.create()
|
|
83
|
+
.provide(UserContext, { id: 1, name: 'Alice' })
|
|
84
|
+
.provide(ConfigContext, config)
|
|
85
|
+
.build();
|
|
86
|
+
|
|
87
|
+
// Accès aux valeurs
|
|
88
|
+
const user = provider.get(UserContext);
|
|
89
|
+
const config = provider.get(ConfigContext);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Factory pour Lazy Initialization
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
const provider = ContextProvider.create()
|
|
96
|
+
.provideFactory(DatabaseContext, () => {
|
|
97
|
+
console.log('Database initialized');
|
|
98
|
+
return createDatabaseConnection();
|
|
99
|
+
})
|
|
100
|
+
.build();
|
|
101
|
+
|
|
102
|
+
// La database n'est initialisée que lors du premier accès
|
|
103
|
+
const db = provider.get(DatabaseContext);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Builder Fluent
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const provider = ContextProviderBuilder.create()
|
|
110
|
+
.provide(UserContext, currentUser)
|
|
111
|
+
.provide(ConfigContext, appConfig)
|
|
112
|
+
.provideFactory(CacheContext, () => new LRUCache())
|
|
113
|
+
.build();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Context Scopes
|
|
117
|
+
|
|
118
|
+
Les scopes définissent la portée de visibilité des contextes.
|
|
119
|
+
|
|
120
|
+
### Types de Scopes
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
enum ContextScope {
|
|
124
|
+
GLOBAL = 'global', // Partagé entre toutes les exécutions
|
|
125
|
+
WORKFLOW = 'workflow', // Partagé dans une exécution de workflow
|
|
126
|
+
STEP = 'step', // Partagé dans une étape de workflow
|
|
127
|
+
AGENT = 'agent', // Spécifique à un agent
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Utilisation des Scopes
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { ContextScope } from 'societyai';
|
|
135
|
+
|
|
136
|
+
const provider = ContextProvider.create()
|
|
137
|
+
// Scope global - partagé partout
|
|
138
|
+
.provide(ConfigContext, config, ContextScope.GLOBAL)
|
|
139
|
+
|
|
140
|
+
// Scope workflow (par défaut)
|
|
141
|
+
.provide(SessionContext, session)
|
|
142
|
+
|
|
143
|
+
// Scope step - réinitialisé à chaque étape
|
|
144
|
+
.provide(TempDataContext, {}, ContextScope.STEP)
|
|
145
|
+
|
|
146
|
+
// Scope agent - spécifique à chaque agent
|
|
147
|
+
.provide(AgentStateContext, {}, ContextScope.AGENT)
|
|
148
|
+
.build();
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Utilisation avec des Agents
|
|
152
|
+
|
|
153
|
+
### Injection dans les Prompts
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { ContextAwarePromptBuilder } from 'societyai';
|
|
157
|
+
|
|
158
|
+
const promptBuilder = new ContextAwarePromptBuilder(provider);
|
|
159
|
+
|
|
160
|
+
const prompt = promptBuilder
|
|
161
|
+
.withSystemPrompt('You are a helpful assistant')
|
|
162
|
+
.withContext({
|
|
163
|
+
user: UserContext,
|
|
164
|
+
config: ConfigContext,
|
|
165
|
+
})
|
|
166
|
+
.withInput(userInput)
|
|
167
|
+
.build();
|
|
168
|
+
|
|
169
|
+
// Le prompt inclura automatiquement les valeurs de contexte
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Agent Context Injector
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { AgentContextInjector } from 'societyai';
|
|
176
|
+
|
|
177
|
+
const injector = new AgentContextInjector(provider);
|
|
178
|
+
|
|
179
|
+
// Injecte le contexte dans la configuration de l'agent
|
|
180
|
+
const enrichedAgent = injector.inject(agentConfig, {
|
|
181
|
+
injectIntoPrompt: true,
|
|
182
|
+
contextTokens: [UserContext, ConfigContext],
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Utilisation dans Society Builder
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const provider = ContextProvider.create()
|
|
190
|
+
.provide(UserContext, currentUser)
|
|
191
|
+
.provide(ApiKeyContext, process.env.API_KEY!)
|
|
192
|
+
.build();
|
|
193
|
+
|
|
194
|
+
const society = Society.create()
|
|
195
|
+
.withName('Contextual Society')
|
|
196
|
+
.withContext(provider) // Attache le provider
|
|
197
|
+
.addAgent((agent) =>
|
|
198
|
+
agent
|
|
199
|
+
.withId('assistant')
|
|
200
|
+
.withRole((r) => r.withSystemPrompt('You are an assistant. User: {context.user.name}'))
|
|
201
|
+
.withModel(model)
|
|
202
|
+
)
|
|
203
|
+
.execute(input);
|
|
204
|
+
|
|
205
|
+
// Le contexte est automatiquement disponible pour tous les agents
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Patterns Avancés
|
|
209
|
+
|
|
210
|
+
### Providers Enfants
|
|
211
|
+
|
|
212
|
+
Créez des contextes hérités pour l'isolation:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const parentProvider = ContextProvider.create().provide(ConfigContext, globalConfig).build();
|
|
216
|
+
|
|
217
|
+
// Le contexte enfant hérite du parent
|
|
218
|
+
const childProvider = parentProvider.createChild();
|
|
219
|
+
childProvider.set(LocalStateContext, localState);
|
|
220
|
+
|
|
221
|
+
// Peut accéder au parent et au local
|
|
222
|
+
const config = childProvider.get(ConfigContext); // Du parent
|
|
223
|
+
const state = childProvider.get(LocalStateContext); // Local
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Merge de Providers
|
|
227
|
+
|
|
228
|
+
Combinez plusieurs providers:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
const provider1 = ContextProvider.create().provide(UserContext, user).build();
|
|
232
|
+
|
|
233
|
+
const provider2 = ContextProvider.create().provide(ConfigContext, config).build();
|
|
234
|
+
|
|
235
|
+
// Merge provider2 dans provider1
|
|
236
|
+
provider1.merge(provider2);
|
|
237
|
+
|
|
238
|
+
// provider1 a maintenant les deux contextes
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Providers Immutables
|
|
242
|
+
|
|
243
|
+
Créez une vue en lecture seule:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const mutableProvider = ContextProvider.create().provide(UserContext, user).build();
|
|
247
|
+
|
|
248
|
+
// Vue immutable
|
|
249
|
+
const immutableView = mutableProvider.freeze();
|
|
250
|
+
|
|
251
|
+
// ✅ Lecture OK
|
|
252
|
+
const user = immutableView.get(UserContext);
|
|
253
|
+
|
|
254
|
+
// ❌ Erreur - pas de méthode set
|
|
255
|
+
// immutableView.set(UserContext, newUser);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Context Store
|
|
259
|
+
|
|
260
|
+
Utilisez le `ContextStore` pour la gestion d'état:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { ContextStore, selectContext, fromObject, toObject } from 'societyai';
|
|
264
|
+
|
|
265
|
+
// Créer depuis un objet
|
|
266
|
+
const store = fromObject({
|
|
267
|
+
user: currentUser,
|
|
268
|
+
config: appConfig,
|
|
269
|
+
session: sessionData,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Sélectionner des valeurs
|
|
273
|
+
const user = selectContext(store, UserContext);
|
|
274
|
+
|
|
275
|
+
// Convertir en objet
|
|
276
|
+
const data = toObject(store);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Common Contexts
|
|
280
|
+
|
|
281
|
+
Utilisez les contextes prédéfinis:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import { CommonContexts } from 'societyai';
|
|
285
|
+
|
|
286
|
+
const provider = ContextProvider.create()
|
|
287
|
+
.provide(CommonContexts.RequestId, generateId())
|
|
288
|
+
.provide(CommonContexts.UserId, userId)
|
|
289
|
+
.provide(CommonContexts.SessionId, sessionId)
|
|
290
|
+
.provide(CommonContexts.Timestamp, Date.now())
|
|
291
|
+
.build();
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Exemples Complets
|
|
295
|
+
|
|
296
|
+
### Exemple 1: Application Web avec Contexte Utilisateur
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import { Society, ContextProvider, createContextToken, ContextScope } from 'societyai';
|
|
300
|
+
|
|
301
|
+
// Définir les tokens
|
|
302
|
+
interface User {
|
|
303
|
+
id: string;
|
|
304
|
+
name: string;
|
|
305
|
+
preferences: Record<string, unknown>;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
interface Request {
|
|
309
|
+
method: string;
|
|
310
|
+
path: string;
|
|
311
|
+
body: unknown;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const UserContext = createContextToken<User>('user');
|
|
315
|
+
const RequestContext = createContextToken<Request>('request');
|
|
316
|
+
const ApiKeyContext = createContextToken<string>('apiKey');
|
|
317
|
+
|
|
318
|
+
// Créer le provider pour une requête
|
|
319
|
+
function createRequestContext(user: User, request: Request) {
|
|
320
|
+
return (
|
|
321
|
+
ContextProvider.create()
|
|
322
|
+
// Config globale
|
|
323
|
+
.provide(ApiKeyContext, process.env.API_KEY!, ContextScope.GLOBAL)
|
|
324
|
+
|
|
325
|
+
// Données de la requête
|
|
326
|
+
.provide(UserContext, user, ContextScope.WORKFLOW)
|
|
327
|
+
.provide(RequestContext, request, ContextScope.WORKFLOW)
|
|
328
|
+
.build()
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Utiliser dans la society
|
|
333
|
+
async function handleRequest(user: User, request: Request) {
|
|
334
|
+
const provider = createRequestContext(user, request);
|
|
335
|
+
|
|
336
|
+
const result = await Society.create()
|
|
337
|
+
.withName('Request Handler')
|
|
338
|
+
.withContext(provider)
|
|
339
|
+
.addAgent((a) =>
|
|
340
|
+
a
|
|
341
|
+
.withId('analyzer')
|
|
342
|
+
.withRole((r) =>
|
|
343
|
+
r.withSystemPrompt(
|
|
344
|
+
`You are analyzing a request for user {context.user.name}.
|
|
345
|
+
Request: {context.request.method} {context.request.path}`
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
.withModel(model)
|
|
349
|
+
)
|
|
350
|
+
.execute(`Analyze: ${JSON.stringify(request.body)}`);
|
|
351
|
+
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Exemple 2: Système Multi-Tenant
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
// Tokens pour multi-tenant
|
|
360
|
+
const TenantContext = createContextToken<Tenant>('tenant');
|
|
361
|
+
const DatabaseContext = createContextToken<Database>('database');
|
|
362
|
+
|
|
363
|
+
// Factory par tenant
|
|
364
|
+
class TenantContextFactory {
|
|
365
|
+
private providers = new Map<string, ContextProvider>();
|
|
366
|
+
|
|
367
|
+
get(tenantId: string): ContextProvider {
|
|
368
|
+
if (!this.providers.has(tenantId)) {
|
|
369
|
+
const tenant = loadTenant(tenantId);
|
|
370
|
+
|
|
371
|
+
const provider = ContextProvider.create()
|
|
372
|
+
.provide(TenantContext, tenant)
|
|
373
|
+
.provideFactory(DatabaseContext, () => {
|
|
374
|
+
// Connexion DB spécifique au tenant
|
|
375
|
+
return createConnection(tenant.dbConfig);
|
|
376
|
+
})
|
|
377
|
+
.build();
|
|
378
|
+
|
|
379
|
+
this.providers.set(tenantId, provider);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return this.providers.get(tenantId)!;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Utilisation
|
|
387
|
+
const factory = new TenantContextFactory();
|
|
388
|
+
|
|
389
|
+
async function processTenantRequest(tenantId: string, input: string) {
|
|
390
|
+
const provider = factory.get(tenantId);
|
|
391
|
+
|
|
392
|
+
return await Society.create().withContext(provider).addAgent(/* ... */).execute(input);
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Exemple 3: Test avec Contextes Mockés
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
// Contextes pour tests
|
|
400
|
+
const MockUserContext = createContextToken<User>('mockUser', {
|
|
401
|
+
id: 'test-user',
|
|
402
|
+
name: 'Test User',
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const MockApiContext = createContextToken<API>('mockApi');
|
|
406
|
+
|
|
407
|
+
// Provider de test
|
|
408
|
+
function createTestContext(): ContextProvider {
|
|
409
|
+
const mockApi = {
|
|
410
|
+
async fetch(url: string) {
|
|
411
|
+
return { data: 'mock data' };
|
|
412
|
+
},
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
return ContextProvider.create()
|
|
416
|
+
.provide(MockUserContext, {
|
|
417
|
+
id: 'test-1',
|
|
418
|
+
name: 'Alice Test',
|
|
419
|
+
})
|
|
420
|
+
.provide(MockApiContext, mockApi)
|
|
421
|
+
.build();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Test
|
|
425
|
+
describe('Society with Context', () => {
|
|
426
|
+
it('should use mock context', async () => {
|
|
427
|
+
const provider = createTestContext();
|
|
428
|
+
|
|
429
|
+
const result = await Society.create()
|
|
430
|
+
.withContext(provider)
|
|
431
|
+
.addAgent(/* ... */)
|
|
432
|
+
.execute('test input');
|
|
433
|
+
|
|
434
|
+
expect(result.success).toBe(true);
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Exemple 4: Context Middleware
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
import { Middleware, MiddlewareContext } from 'societyai';
|
|
443
|
+
|
|
444
|
+
// Middleware qui injecte le contexte
|
|
445
|
+
const contextMiddleware = (provider: ContextProvider): Middleware => ({
|
|
446
|
+
name: 'context-injection',
|
|
447
|
+
fn: async (ctx: MiddlewareContext, next) => {
|
|
448
|
+
// Injecter les contextes dans metadata
|
|
449
|
+
ctx.metadata.set('contextProvider', provider);
|
|
450
|
+
|
|
451
|
+
// Enrichir l'input avec le contexte
|
|
452
|
+
const user = provider.getOptional(UserContext);
|
|
453
|
+
if (user) {
|
|
454
|
+
ctx.processedInput = `[User: ${user.name}] ${ctx.input}`;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return await next(ctx);
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// Utilisation
|
|
462
|
+
const chain = MiddlewareChain.create()
|
|
463
|
+
.use(contextMiddleware(provider))
|
|
464
|
+
.use(Middlewares.logging())
|
|
465
|
+
.build();
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Bonnes Pratiques
|
|
469
|
+
|
|
470
|
+
### 1. Nommage des Tokens
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
// ✅ Bon - noms descriptifs
|
|
474
|
+
const UserContext = createContextToken<User>('user');
|
|
475
|
+
const DatabaseContext = createContextToken<Database>('database');
|
|
476
|
+
|
|
477
|
+
// ❌ Mauvais - noms génériques
|
|
478
|
+
const Context1 = createContextToken<any>('ctx1');
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### 2. Typage Fort
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
// ✅ Bon - interfaces bien définies
|
|
485
|
+
interface AppConfig {
|
|
486
|
+
apiUrl: string;
|
|
487
|
+
timeout: number;
|
|
488
|
+
retries: number;
|
|
489
|
+
}
|
|
490
|
+
const ConfigContext = createContextToken<AppConfig>('config');
|
|
491
|
+
|
|
492
|
+
// ❌ Mauvais - typage faible
|
|
493
|
+
const ConfigContext = createContextToken<any>('config');
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### 3. Valeurs par Défaut
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
// ✅ Bon - valeurs par défaut sensées
|
|
500
|
+
const TimeoutContext = createContextToken<number>('timeout', 5000);
|
|
501
|
+
|
|
502
|
+
// ✅ Bon - config par défaut complète
|
|
503
|
+
const defaultConfig: AppConfig = {
|
|
504
|
+
apiUrl: process.env.API_URL || 'http://localhost',
|
|
505
|
+
timeout: 5000,
|
|
506
|
+
retries: 3,
|
|
507
|
+
};
|
|
508
|
+
const ConfigContext = createContextToken<AppConfig>('config', defaultConfig);
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### 4. Lazy Initialization
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
// ✅ Bon - ressources coûteuses en lazy
|
|
515
|
+
provider.provideFactory(DatabaseContext, () => createConnection());
|
|
516
|
+
provider.provideFactory(CacheContext, () => new LRUCache(100));
|
|
517
|
+
|
|
518
|
+
// ❌ Mauvais - initialisation immédiate
|
|
519
|
+
provider.provide(DatabaseContext, createConnection());
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### 5. Scopes Appropriés
|
|
523
|
+
|
|
524
|
+
```typescript
|
|
525
|
+
// ✅ Bon - scope adapté au cycle de vie
|
|
526
|
+
provider.provide(ConfigContext, config, ContextScope.GLOBAL);
|
|
527
|
+
provider.provide(SessionContext, session, ContextScope.WORKFLOW);
|
|
528
|
+
provider.provide(TempDataContext, {}, ContextScope.STEP);
|
|
529
|
+
|
|
530
|
+
// ❌ Mauvais - tout en global
|
|
531
|
+
provider.provide(SessionContext, session, ContextScope.GLOBAL);
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
## API Reference
|
|
535
|
+
|
|
536
|
+
### `createContextToken<T>(name, defaultValue?)`
|
|
537
|
+
|
|
538
|
+
Crée un token de contexte type-safe.
|
|
539
|
+
|
|
540
|
+
**Paramètres:**
|
|
541
|
+
|
|
542
|
+
- `name: string` - Nom unique du token
|
|
543
|
+
- `defaultValue?: T` - Valeur par défaut optionnelle
|
|
544
|
+
|
|
545
|
+
**Retourne:** `ContextToken<T>`
|
|
546
|
+
|
|
547
|
+
### `ContextProvider.create()`
|
|
548
|
+
|
|
549
|
+
Crée un nouveau builder de context provider.
|
|
550
|
+
|
|
551
|
+
**Retourne:** `ContextProviderBuilder`
|
|
552
|
+
|
|
553
|
+
### `ContextProvider.empty()`
|
|
554
|
+
|
|
555
|
+
Crée un provider vide.
|
|
556
|
+
|
|
557
|
+
**Retourne:** `ContextProvider`
|
|
558
|
+
|
|
559
|
+
### `provider.provide<T>(token, value, scope?)`
|
|
560
|
+
|
|
561
|
+
Fournit une valeur pour un token.
|
|
562
|
+
|
|
563
|
+
**Paramètres:**
|
|
564
|
+
|
|
565
|
+
- `token: ContextToken<T>` - Le token
|
|
566
|
+
- `value: T` - La valeur
|
|
567
|
+
- `scope?: ContextScope` - Le scope (défaut: WORKFLOW)
|
|
568
|
+
|
|
569
|
+
**Retourne:** `this`
|
|
570
|
+
|
|
571
|
+
### `provider.provideFactory<T>(token, factory, scope?)`
|
|
572
|
+
|
|
573
|
+
Fournit une factory pour lazy initialization.
|
|
574
|
+
|
|
575
|
+
**Paramètres:**
|
|
576
|
+
|
|
577
|
+
- `token: ContextToken<T>` - Le token
|
|
578
|
+
- `factory: () => T` - La fonction factory
|
|
579
|
+
- `scope?: ContextScope` - Le scope (défaut: WORKFLOW)
|
|
580
|
+
|
|
581
|
+
**Retourne:** `this`
|
|
582
|
+
|
|
583
|
+
### `provider.get<T>(token)`
|
|
584
|
+
|
|
585
|
+
Récupère une valeur de contexte.
|
|
586
|
+
|
|
587
|
+
**Paramètres:**
|
|
588
|
+
|
|
589
|
+
- `token: ContextToken<T>` - Le token
|
|
590
|
+
|
|
591
|
+
**Retourne:** `T`
|
|
592
|
+
|
|
593
|
+
**Throws:** `Error` si le contexte n'est pas fourni
|
|
594
|
+
|
|
595
|
+
### `provider.getOptional<T>(token)`
|
|
596
|
+
|
|
597
|
+
Récupère une valeur de contexte ou undefined.
|
|
598
|
+
|
|
599
|
+
**Paramètres:**
|
|
600
|
+
|
|
601
|
+
- `token: ContextToken<T>` - Le token
|
|
602
|
+
|
|
603
|
+
**Retourne:** `T | undefined`
|
|
604
|
+
|
|
605
|
+
### `provider.has<T>(token)`
|
|
606
|
+
|
|
607
|
+
Vérifie si un contexte est fourni.
|
|
608
|
+
|
|
609
|
+
**Paramètres:**
|
|
610
|
+
|
|
611
|
+
- `token: ContextToken<T>` - Le token
|
|
612
|
+
|
|
613
|
+
**Retourne:** `boolean`
|
|
614
|
+
|
|
615
|
+
### `provider.createChild()`
|
|
616
|
+
|
|
617
|
+
Crée un provider enfant qui hérite du parent.
|
|
618
|
+
|
|
619
|
+
**Retourne:** `ContextProvider`
|
|
620
|
+
|
|
621
|
+
### `provider.merge(other)`
|
|
622
|
+
|
|
623
|
+
Fusionne un autre provider dans celui-ci.
|
|
624
|
+
|
|
625
|
+
**Paramètres:**
|
|
626
|
+
|
|
627
|
+
- `other: ContextProvider` - Le provider à fusionner
|
|
628
|
+
|
|
629
|
+
**Retourne:** `this`
|
|
630
|
+
|
|
631
|
+
### `provider.freeze()`
|
|
632
|
+
|
|
633
|
+
Crée une vue immutable du provider.
|
|
634
|
+
|
|
635
|
+
**Retourne:** `IContextProvider`
|
|
636
|
+
|
|
637
|
+
## Voir Aussi
|
|
638
|
+
|
|
639
|
+
- [Architecture](./architecture.md) - Concepts de base
|
|
640
|
+
- [Workflows](./workflows.md) - Utilisation du contexte dans les workflows
|
|
641
|
+
- [Middleware System](./middleware.md) - Intégration avec les middlewares
|
|
642
|
+
- [Advanced Features](./advanced.md) - Patterns avancés
|