agentic-flow 1.8.10 → 1.8.13

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 (33) hide show
  1. package/dist/agents/claudeAgent.js +50 -0
  2. package/dist/cli/federation-cli.d.ts +53 -0
  3. package/dist/cli/federation-cli.js +431 -0
  4. package/dist/cli-proxy.js +28 -1
  5. package/dist/federation/EphemeralAgent.js +258 -0
  6. package/dist/federation/FederationHub.js +283 -0
  7. package/dist/federation/FederationHubClient.js +212 -0
  8. package/dist/federation/FederationHubServer.js +436 -0
  9. package/dist/federation/SecurityManager.js +191 -0
  10. package/dist/federation/debug/agent-debug-stream.js +474 -0
  11. package/dist/federation/debug/debug-stream.js +419 -0
  12. package/dist/federation/index.js +12 -0
  13. package/dist/federation/integrations/realtime-federation.js +404 -0
  14. package/dist/federation/integrations/supabase-adapter-debug.js +400 -0
  15. package/dist/federation/integrations/supabase-adapter.js +258 -0
  16. package/dist/index.js +18 -1
  17. package/dist/utils/cli.js +5 -0
  18. package/docs/architecture/FEDERATION-DATA-LIFECYCLE.md +520 -0
  19. package/docs/federation/AGENT-DEBUG-STREAMING.md +403 -0
  20. package/docs/federation/DEBUG-STREAMING-COMPLETE.md +432 -0
  21. package/docs/federation/DEBUG-STREAMING.md +537 -0
  22. package/docs/federation/DEPLOYMENT-VALIDATION-SUCCESS.md +394 -0
  23. package/docs/federation/DOCKER-FEDERATION-DEEP-REVIEW.md +478 -0
  24. package/docs/issues/ISSUE-SUPABASE-INTEGRATION.md +536 -0
  25. package/docs/supabase/IMPLEMENTATION-SUMMARY.md +498 -0
  26. package/docs/supabase/INDEX.md +358 -0
  27. package/docs/supabase/QUICKSTART.md +365 -0
  28. package/docs/supabase/README.md +318 -0
  29. package/docs/supabase/SUPABASE-REALTIME-FEDERATION.md +575 -0
  30. package/docs/supabase/TEST-REPORT.md +446 -0
  31. package/docs/supabase/migrations/001_create_federation_tables.sql +339 -0
  32. package/docs/validation/reports/REGRESSION-TEST-V1.8.11.md +456 -0
  33. package/package.json +4 -1
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Security Manager - Authentication, encryption, and access control
3
+ *
4
+ * Features:
5
+ * - JWT token generation and validation
6
+ * - AES-256 encryption for data at rest
7
+ * - Tenant isolation
8
+ * - mTLS certificate management
9
+ */
10
+ import crypto from 'crypto';
11
+ import { logger } from '../utils/logger.js';
12
+ export class SecurityManager {
13
+ algorithm = 'aes-256-gcm';
14
+ jwtSecret;
15
+ encryptionCache = new Map();
16
+ constructor() {
17
+ // In production, load from secure vault (AWS Secrets Manager, HashiCorp Vault, etc.)
18
+ this.jwtSecret = process.env.JWT_SECRET || crypto.randomBytes(32).toString('hex');
19
+ }
20
+ /**
21
+ * Create JWT token for agent authentication
22
+ */
23
+ async createAgentToken(payload) {
24
+ const header = {
25
+ alg: 'HS256',
26
+ typ: 'JWT'
27
+ };
28
+ const now = Date.now();
29
+ const tokenPayload = {
30
+ ...payload,
31
+ iat: now,
32
+ exp: payload.expiresAt,
33
+ iss: 'agentic-flow-federation'
34
+ };
35
+ // Encode header and payload
36
+ const encodedHeader = this.base64UrlEncode(JSON.stringify(header));
37
+ const encodedPayload = this.base64UrlEncode(JSON.stringify(tokenPayload));
38
+ // Create signature
39
+ const signature = crypto
40
+ .createHmac('sha256', this.jwtSecret)
41
+ .update(`${encodedHeader}.${encodedPayload}`)
42
+ .digest('base64url');
43
+ const token = `${encodedHeader}.${encodedPayload}.${signature}`;
44
+ logger.info('Created agent token', {
45
+ agentId: payload.agentId,
46
+ tenantId: payload.tenantId,
47
+ expiresAt: new Date(payload.expiresAt).toISOString()
48
+ });
49
+ return token;
50
+ }
51
+ /**
52
+ * Verify JWT token
53
+ */
54
+ async verifyAgentToken(token) {
55
+ const parts = token.split('.');
56
+ if (parts.length !== 3) {
57
+ throw new Error('Invalid token format');
58
+ }
59
+ const [encodedHeader, encodedPayload, signature] = parts;
60
+ // Verify signature
61
+ const expectedSignature = crypto
62
+ .createHmac('sha256', this.jwtSecret)
63
+ .update(`${encodedHeader}.${encodedPayload}`)
64
+ .digest('base64url');
65
+ if (signature !== expectedSignature) {
66
+ throw new Error('Invalid token signature');
67
+ }
68
+ // Decode payload
69
+ const payload = JSON.parse(this.base64UrlDecode(encodedPayload));
70
+ // Check expiration
71
+ if (Date.now() >= payload.exp) {
72
+ throw new Error('Token expired');
73
+ }
74
+ logger.debug('Token verified', {
75
+ agentId: payload.agentId,
76
+ tenantId: payload.tenantId
77
+ });
78
+ return payload;
79
+ }
80
+ /**
81
+ * Get or create encryption keys for a tenant
82
+ */
83
+ async getEncryptionKeys(tenantId) {
84
+ // Check cache
85
+ if (this.encryptionCache.has(tenantId)) {
86
+ return this.encryptionCache.get(tenantId);
87
+ }
88
+ // Generate new keys for tenant
89
+ // In production, these would be stored in a secure key management service
90
+ const encryptionKey = crypto.randomBytes(32); // 256-bit key
91
+ const iv = crypto.randomBytes(16); // 128-bit IV
92
+ const keys = { encryptionKey, iv };
93
+ // Cache keys
94
+ this.encryptionCache.set(tenantId, keys);
95
+ logger.info('Generated encryption keys for tenant', { tenantId });
96
+ return keys;
97
+ }
98
+ /**
99
+ * Encrypt data with AES-256-GCM
100
+ */
101
+ async encrypt(data, tenantId) {
102
+ const keys = await this.getEncryptionKeys(tenantId);
103
+ const cipher = crypto.createCipheriv(this.algorithm, keys.encryptionKey, keys.iv);
104
+ let encrypted = cipher.update(data, 'utf8', 'base64');
105
+ encrypted += cipher.final('base64');
106
+ const authTag = cipher.getAuthTag().toString('base64');
107
+ logger.debug('Data encrypted', {
108
+ tenantId,
109
+ originalLength: data.length,
110
+ encryptedLength: encrypted.length
111
+ });
112
+ return { encrypted, authTag };
113
+ }
114
+ /**
115
+ * Decrypt data with AES-256-GCM
116
+ */
117
+ async decrypt(encrypted, authTag, tenantId) {
118
+ const keys = await this.getEncryptionKeys(tenantId);
119
+ const decipher = crypto.createDecipheriv(this.algorithm, keys.encryptionKey, keys.iv);
120
+ decipher.setAuthTag(Buffer.from(authTag, 'base64'));
121
+ let decrypted = decipher.update(encrypted, 'base64', 'utf8');
122
+ decrypted += decipher.final('utf8');
123
+ logger.debug('Data decrypted', {
124
+ tenantId,
125
+ decryptedLength: decrypted.length
126
+ });
127
+ return decrypted;
128
+ }
129
+ /**
130
+ * Generate mTLS certificates for agent-to-hub communication
131
+ */
132
+ async generateMTLSCertificates(agentId) {
133
+ // Placeholder: Actual implementation would use OpenSSL or similar
134
+ // to generate X.509 certificates with proper CA chain
135
+ logger.info('Generating mTLS certificates', { agentId });
136
+ return {
137
+ cert: 'PLACEHOLDER_CERT',
138
+ key: 'PLACEHOLDER_KEY',
139
+ ca: 'PLACEHOLDER_CA'
140
+ };
141
+ }
142
+ /**
143
+ * Validate tenant access to data
144
+ */
145
+ validateTenantAccess(requestTenantId, dataTenantId) {
146
+ if (requestTenantId !== dataTenantId) {
147
+ logger.warn('Tenant access violation detected', {
148
+ requestTenantId,
149
+ dataTenantId
150
+ });
151
+ return false;
152
+ }
153
+ return true;
154
+ }
155
+ /**
156
+ * Hash sensitive data for storage (one-way)
157
+ */
158
+ hashData(data) {
159
+ return crypto.createHash('sha256').update(data).digest('hex');
160
+ }
161
+ /**
162
+ * Generate secure random ID
163
+ */
164
+ generateSecureId() {
165
+ return crypto.randomBytes(16).toString('hex');
166
+ }
167
+ /**
168
+ * Base64 URL-safe encoding
169
+ */
170
+ base64UrlEncode(str) {
171
+ return Buffer.from(str)
172
+ .toString('base64')
173
+ .replace(/\+/g, '-')
174
+ .replace(/\//g, '_')
175
+ .replace(/=/g, '');
176
+ }
177
+ /**
178
+ * Base64 URL-safe decoding
179
+ */
180
+ base64UrlDecode(str) {
181
+ const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
182
+ return Buffer.from(base64, 'base64').toString('utf8');
183
+ }
184
+ /**
185
+ * Clear cached keys (for testing or security refresh)
186
+ */
187
+ clearCache() {
188
+ this.encryptionCache.clear();
189
+ logger.info('Encryption cache cleared');
190
+ }
191
+ }
@@ -0,0 +1,474 @@
1
+ /**
2
+ * Single Agent Debug Streaming
3
+ *
4
+ * Provides detailed visibility into a single agent's operations,
5
+ * lifecycle, and internal state changes.
6
+ *
7
+ * Features:
8
+ * - Agent lifecycle tracking (spawn → work → shutdown)
9
+ * - Task execution tracing
10
+ * - Memory operations
11
+ * - Communication events
12
+ * - Decision logging
13
+ * - State transitions
14
+ * - Performance metrics
15
+ * - Timeline visualization
16
+ */
17
+ import { EventEmitter } from 'events';
18
+ import { DebugLevel, createDebugStream } from './debug-stream.js';
19
+ // Re-export DebugLevel for convenience
20
+ export { DebugLevel } from './debug-stream.js';
21
+ export class AgentDebugStream extends EventEmitter {
22
+ config;
23
+ debug;
24
+ state;
25
+ decisions = [];
26
+ tasks = new Map();
27
+ communications = [];
28
+ timeline = [];
29
+ performanceMetrics = new Map();
30
+ constructor(config) {
31
+ super();
32
+ this.config = config;
33
+ // Initialize base debug stream
34
+ this.debug = createDebugStream({
35
+ level: config.level ?? DebugLevel.VERBOSE,
36
+ format: config.format === 'timeline' ? 'human' : config.format,
37
+ output: config.output ?? 'console',
38
+ outputFile: config.outputFile,
39
+ colorize: config.colorize ?? true,
40
+ });
41
+ // Initialize state
42
+ this.state = {
43
+ phase: 'spawning',
44
+ startTime: new Date().toISOString(),
45
+ metadata: {},
46
+ };
47
+ this.logAgentPhase('spawning', { agentId: config.agentId });
48
+ }
49
+ /**
50
+ * Log agent lifecycle phase change
51
+ */
52
+ logAgentPhase(phase, data) {
53
+ const oldPhase = this.state.phase;
54
+ this.state.phase = phase;
55
+ this.state.lastActivity = new Date().toISOString();
56
+ this.debug.log({
57
+ level: DebugLevel.BASIC,
58
+ category: 'agent_lifecycle',
59
+ operation: `phase_${phase}`,
60
+ agentId: this.config.agentId,
61
+ tenantId: this.config.tenantId,
62
+ data: {
63
+ old_phase: oldPhase,
64
+ new_phase: phase,
65
+ ...data,
66
+ },
67
+ });
68
+ if (this.config.timeline) {
69
+ this.timeline.push({
70
+ timestamp: new Date().toISOString(),
71
+ type: 'phase_change',
72
+ from: oldPhase,
73
+ to: phase,
74
+ data,
75
+ });
76
+ }
77
+ this.emit('phase_change', { from: oldPhase, to: phase, data });
78
+ }
79
+ /**
80
+ * Log agent initialization
81
+ */
82
+ logInitialization(config) {
83
+ this.logAgentPhase('initializing', { config });
84
+ this.debug.log({
85
+ level: DebugLevel.DETAILED,
86
+ category: 'agent_lifecycle',
87
+ operation: 'initialize',
88
+ agentId: this.config.agentId,
89
+ tenantId: this.config.tenantId,
90
+ data: config,
91
+ });
92
+ }
93
+ /**
94
+ * Log agent ready
95
+ */
96
+ logReady(capabilities) {
97
+ this.logAgentPhase('ready', { capabilities });
98
+ this.debug.log({
99
+ level: DebugLevel.BASIC,
100
+ category: 'agent_lifecycle',
101
+ operation: 'ready',
102
+ agentId: this.config.agentId,
103
+ tenantId: this.config.tenantId,
104
+ data: { capabilities },
105
+ });
106
+ }
107
+ /**
108
+ * Start tracking a task
109
+ */
110
+ startTask(taskId, description, data) {
111
+ const task = {
112
+ taskId,
113
+ description,
114
+ startTime: new Date().toISOString(),
115
+ status: 'running',
116
+ steps: [],
117
+ };
118
+ this.tasks.set(taskId, task);
119
+ this.state.task = description;
120
+ this.state.taskId = taskId;
121
+ this.logAgentPhase('working', { taskId, description });
122
+ this.debug.log({
123
+ level: DebugLevel.VERBOSE,
124
+ category: 'task',
125
+ operation: 'task_start',
126
+ agentId: this.config.agentId,
127
+ tenantId: this.config.tenantId,
128
+ data: { taskId, description, ...data },
129
+ });
130
+ if (this.config.timeline) {
131
+ this.timeline.push({
132
+ timestamp: new Date().toISOString(),
133
+ type: 'task_start',
134
+ taskId,
135
+ description,
136
+ });
137
+ }
138
+ }
139
+ /**
140
+ * Log task step
141
+ */
142
+ logTaskStep(taskId, step, operation, data) {
143
+ const task = this.tasks.get(taskId);
144
+ if (!task)
145
+ return;
146
+ const stepData = {
147
+ step,
148
+ operation,
149
+ startTime: new Date().toISOString(),
150
+ data,
151
+ };
152
+ task.steps.push(stepData);
153
+ this.debug.log({
154
+ level: DebugLevel.VERBOSE,
155
+ category: 'task_step',
156
+ operation,
157
+ agentId: this.config.agentId,
158
+ tenantId: this.config.tenantId,
159
+ data: {
160
+ taskId,
161
+ step,
162
+ operation,
163
+ ...data,
164
+ },
165
+ });
166
+ }
167
+ /**
168
+ * Complete task step
169
+ */
170
+ completeTaskStep(taskId, step, duration, data) {
171
+ const task = this.tasks.get(taskId);
172
+ if (!task || !task.steps[step])
173
+ return;
174
+ task.steps[step].endTime = new Date().toISOString();
175
+ task.steps[step].duration = duration;
176
+ task.steps[step].data = { ...task.steps[step].data, ...data };
177
+ this.debug.log({
178
+ level: DebugLevel.VERBOSE,
179
+ category: 'task_step',
180
+ operation: 'step_complete',
181
+ agentId: this.config.agentId,
182
+ tenantId: this.config.tenantId,
183
+ data: {
184
+ taskId,
185
+ step,
186
+ duration,
187
+ ...data,
188
+ },
189
+ });
190
+ // Track performance
191
+ this.trackPerformance(`step_${task.steps[step].operation}`, duration);
192
+ }
193
+ /**
194
+ * Complete task
195
+ */
196
+ completeTask(taskId, result) {
197
+ const task = this.tasks.get(taskId);
198
+ if (!task)
199
+ return;
200
+ task.endTime = new Date().toISOString();
201
+ task.status = 'completed';
202
+ task.result = result;
203
+ const duration = new Date(task.endTime).getTime() - new Date(task.startTime).getTime();
204
+ this.debug.log({
205
+ level: DebugLevel.VERBOSE,
206
+ category: 'task',
207
+ operation: 'task_complete',
208
+ agentId: this.config.agentId,
209
+ tenantId: this.config.tenantId,
210
+ data: {
211
+ taskId,
212
+ duration,
213
+ steps: task.steps.length,
214
+ result,
215
+ },
216
+ });
217
+ if (this.config.timeline) {
218
+ this.timeline.push({
219
+ timestamp: new Date().toISOString(),
220
+ type: 'task_complete',
221
+ taskId,
222
+ duration,
223
+ });
224
+ }
225
+ this.trackPerformance('task_completion', duration);
226
+ this.state.task = undefined;
227
+ this.state.taskId = undefined;
228
+ this.logAgentPhase('idle');
229
+ }
230
+ /**
231
+ * Fail task
232
+ */
233
+ failTask(taskId, error) {
234
+ const task = this.tasks.get(taskId);
235
+ if (!task)
236
+ return;
237
+ task.endTime = new Date().toISOString();
238
+ task.status = 'failed';
239
+ task.error = error;
240
+ this.debug.log({
241
+ level: DebugLevel.BASIC,
242
+ category: 'task',
243
+ operation: 'task_failed',
244
+ agentId: this.config.agentId,
245
+ tenantId: this.config.tenantId,
246
+ data: {
247
+ taskId,
248
+ error: error.message,
249
+ },
250
+ error,
251
+ });
252
+ this.state.task = undefined;
253
+ this.state.taskId = undefined;
254
+ this.logAgentPhase('idle');
255
+ }
256
+ /**
257
+ * Log a decision
258
+ */
259
+ logDecision(context, options, selected, reasoning, confidence) {
260
+ if (!this.config.trackDecisions)
261
+ return;
262
+ const decision = {
263
+ timestamp: new Date().toISOString(),
264
+ context,
265
+ options,
266
+ selected,
267
+ reasoning,
268
+ confidence,
269
+ };
270
+ this.decisions.push(decision);
271
+ this.debug.log({
272
+ level: DebugLevel.VERBOSE,
273
+ category: 'decision',
274
+ operation: 'decision_made',
275
+ agentId: this.config.agentId,
276
+ tenantId: this.config.tenantId,
277
+ data: {
278
+ context,
279
+ options_count: options.length,
280
+ selected,
281
+ reasoning,
282
+ confidence,
283
+ },
284
+ });
285
+ this.emit('decision', decision);
286
+ }
287
+ /**
288
+ * Log communication
289
+ */
290
+ logCommunication(type, target, message) {
291
+ if (!this.config.trackCommunication)
292
+ return;
293
+ const comm = {
294
+ timestamp: new Date().toISOString(),
295
+ type,
296
+ target,
297
+ message,
298
+ };
299
+ this.communications.push(comm);
300
+ this.debug.log({
301
+ level: DebugLevel.VERBOSE,
302
+ category: 'communication',
303
+ operation: type === 'send' ? 'message_sent' : 'message_received',
304
+ agentId: this.config.agentId,
305
+ tenantId: this.config.tenantId,
306
+ data: {
307
+ target,
308
+ message_type: typeof message === 'object' ? message.type : 'unknown',
309
+ size: JSON.stringify(message).length,
310
+ },
311
+ });
312
+ this.emit('communication', comm);
313
+ }
314
+ /**
315
+ * Log memory operation
316
+ */
317
+ logMemoryOperation(operation, data, duration) {
318
+ this.debug.logMemory(operation, this.config.agentId, this.config.tenantId, data, duration);
319
+ if (duration) {
320
+ this.trackPerformance(`memory_${operation}`, duration);
321
+ }
322
+ }
323
+ /**
324
+ * Log thought/reasoning
325
+ */
326
+ logThought(thought, context) {
327
+ this.debug.log({
328
+ level: DebugLevel.TRACE,
329
+ category: 'reasoning',
330
+ operation: 'thought',
331
+ agentId: this.config.agentId,
332
+ tenantId: this.config.tenantId,
333
+ data: {
334
+ thought,
335
+ context,
336
+ },
337
+ });
338
+ }
339
+ /**
340
+ * Log agent shutdown
341
+ */
342
+ logShutdown(reason) {
343
+ this.logAgentPhase('shutting_down', { reason });
344
+ const uptime = new Date().getTime() - new Date(this.state.startTime).getTime();
345
+ this.debug.log({
346
+ level: DebugLevel.BASIC,
347
+ category: 'agent_lifecycle',
348
+ operation: 'shutdown',
349
+ agentId: this.config.agentId,
350
+ tenantId: this.config.tenantId,
351
+ data: {
352
+ reason,
353
+ uptime_ms: uptime,
354
+ total_tasks: this.tasks.size,
355
+ total_decisions: this.decisions.length,
356
+ total_communications: this.communications.length,
357
+ },
358
+ });
359
+ // Print final summary
360
+ this.printSummary();
361
+ this.logAgentPhase('dead');
362
+ }
363
+ /**
364
+ * Track performance metric
365
+ */
366
+ trackPerformance(operation, duration) {
367
+ if (!this.performanceMetrics.has(operation)) {
368
+ this.performanceMetrics.set(operation, []);
369
+ }
370
+ this.performanceMetrics.get(operation).push(duration);
371
+ }
372
+ /**
373
+ * Print agent summary
374
+ */
375
+ printSummary() {
376
+ const uptime = new Date().getTime() - new Date(this.state.startTime).getTime();
377
+ console.log('\n' + '='.repeat(60));
378
+ console.log(`📊 Agent Summary: ${this.config.agentId}`);
379
+ console.log('='.repeat(60));
380
+ console.log('');
381
+ console.log(`Uptime: ${(uptime / 1000).toFixed(2)}s`);
382
+ console.log(`Tasks Completed: ${Array.from(this.tasks.values()).filter(t => t.status === 'completed').length}`);
383
+ console.log(`Tasks Failed: ${Array.from(this.tasks.values()).filter(t => t.status === 'failed').length}`);
384
+ console.log(`Decisions Made: ${this.decisions.length}`);
385
+ console.log(`Messages Sent: ${this.communications.filter(c => c.type === 'send').length}`);
386
+ console.log(`Messages Recv: ${this.communications.filter(c => c.type === 'receive').length}`);
387
+ console.log('');
388
+ // Performance metrics
389
+ if (this.performanceMetrics.size > 0) {
390
+ console.log('Performance Metrics:');
391
+ console.log('-'.repeat(60));
392
+ for (const [operation, durations] of this.performanceMetrics.entries()) {
393
+ const avg = durations.reduce((a, b) => a + b, 0) / durations.length;
394
+ const min = Math.min(...durations);
395
+ const max = Math.max(...durations);
396
+ console.log(` ${operation.padEnd(30)} ${durations.length}x avg: ${avg.toFixed(1)}ms min: ${min.toFixed(1)}ms max: ${max.toFixed(1)}ms`);
397
+ }
398
+ console.log('');
399
+ }
400
+ console.log('='.repeat(60) + '\n');
401
+ }
402
+ /**
403
+ * Print timeline
404
+ */
405
+ printTimeline() {
406
+ if (!this.config.timeline || this.timeline.length === 0)
407
+ return;
408
+ console.log('\n' + '='.repeat(60));
409
+ console.log('📅 Agent Timeline');
410
+ console.log('='.repeat(60) + '\n');
411
+ const startTime = new Date(this.timeline[0].timestamp).getTime();
412
+ for (const event of this.timeline) {
413
+ const elapsed = new Date(event.timestamp).getTime() - startTime;
414
+ const time = `+${(elapsed / 1000).toFixed(3)}s`;
415
+ console.log(`${time.padStart(10)} | ${event.type.padEnd(20)} | ${JSON.stringify(event.data || event)}`);
416
+ }
417
+ console.log('\n' + '='.repeat(60) + '\n');
418
+ }
419
+ /**
420
+ * Get current state
421
+ */
422
+ getState() {
423
+ return { ...this.state };
424
+ }
425
+ /**
426
+ * Get task history
427
+ */
428
+ getTasks() {
429
+ return Array.from(this.tasks.values());
430
+ }
431
+ /**
432
+ * Get decisions
433
+ */
434
+ getDecisions() {
435
+ return [...this.decisions];
436
+ }
437
+ /**
438
+ * Get communications
439
+ */
440
+ getCommunications() {
441
+ return [...this.communications];
442
+ }
443
+ /**
444
+ * Close debug stream
445
+ */
446
+ close() {
447
+ this.debug.close();
448
+ }
449
+ }
450
+ /**
451
+ * Create agent debug stream
452
+ */
453
+ export function createAgentDebugStream(config) {
454
+ return new AgentDebugStream(config);
455
+ }
456
+ /**
457
+ * Create from environment variables
458
+ */
459
+ export function createAgentDebugStreamFromEnv(agentId, tenantId) {
460
+ const debugLevel = process.env.DEBUG_LEVEL?.toUpperCase() || 'VERBOSE';
461
+ return new AgentDebugStream({
462
+ agentId,
463
+ tenantId: tenantId || process.env.FEDERATION_TENANT_ID,
464
+ level: DebugLevel[debugLevel] || DebugLevel.VERBOSE,
465
+ format: process.env.DEBUG_FORMAT || 'human',
466
+ output: process.env.DEBUG_OUTPUT || 'console',
467
+ outputFile: process.env.DEBUG_OUTPUT_FILE,
468
+ colorize: process.env.DEBUG_COLORIZE !== 'false',
469
+ trackState: process.env.DEBUG_TRACK_STATE !== 'false',
470
+ trackDecisions: process.env.DEBUG_TRACK_DECISIONS !== 'false',
471
+ trackCommunication: process.env.DEBUG_TRACK_COMMUNICATION !== 'false',
472
+ timeline: process.env.DEBUG_TIMELINE === 'true',
473
+ });
474
+ }