elsabro 2.3.0 → 3.8.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.
- package/README.md +698 -20
- package/bin/install.js +0 -0
- package/flows/development-flow.json +452 -0
- package/flows/quick-flow.json +118 -0
- package/hooks/hooks-config-updated.json +285 -0
- package/hooks/skill-discovery.sh +539 -0
- package/package.json +3 -2
- package/references/SYSTEM_INDEX.md +400 -5
- package/references/agent-marketplace.md +2274 -0
- package/references/agent-protocol.md +1126 -0
- package/references/ai-code-suggestions.md +2413 -0
- package/references/checkpointing.md +595 -0
- package/references/collaboration-patterns.md +851 -0
- package/references/collaborative-sessions.md +1081 -0
- package/references/configuration-management.md +1810 -0
- package/references/cost-tracking.md +1095 -0
- package/references/enterprise-sso.md +2001 -0
- package/references/error-contracts-v2.md +968 -0
- package/references/event-driven.md +1031 -0
- package/references/flow-orchestration.md +940 -0
- package/references/flow-visualization.md +1557 -0
- package/references/ide-integrations.md +3513 -0
- package/references/interrupt-system.md +681 -0
- package/references/kubernetes-deployment.md +3099 -0
- package/references/memory-system.md +683 -0
- package/references/mobile-companion.md +3236 -0
- package/references/multi-llm-providers.md +2494 -0
- package/references/multi-project-memory.md +1182 -0
- package/references/observability.md +793 -0
- package/references/output-schemas.md +858 -0
- package/references/performance-profiler.md +955 -0
- package/references/plugin-system.md +1526 -0
- package/references/prompt-management.md +292 -0
- package/references/sandbox-execution.md +303 -0
- package/references/security-system.md +1253 -0
- package/references/skill-marketplace-integration.md +3901 -0
- package/references/streaming.md +696 -0
- package/references/testing-framework.md +1151 -0
- package/references/time-travel.md +802 -0
- package/references/tool-registry.md +886 -0
- package/references/voice-commands.md +3296 -0
- package/templates/agent-marketplace-config.json +220 -0
- package/templates/agent-protocol-config.json +136 -0
- package/templates/ai-suggestions-config.json +100 -0
- package/templates/checkpoint-state.json +61 -0
- package/templates/collaboration-config.json +157 -0
- package/templates/collaborative-sessions-config.json +153 -0
- package/templates/configuration-config.json +245 -0
- package/templates/cost-tracking-config.json +148 -0
- package/templates/enterprise-sso-config.json +438 -0
- package/templates/events-config.json +148 -0
- package/templates/flow-visualization-config.json +196 -0
- package/templates/ide-integrations-config.json +442 -0
- package/templates/kubernetes-config.json +764 -0
- package/templates/memory-state.json +84 -0
- package/templates/mobile-companion-config.json +600 -0
- package/templates/multi-llm-config.json +544 -0
- package/templates/multi-project-memory-config.json +145 -0
- package/templates/observability-config.json +109 -0
- package/templates/performance-profiler-config.json +125 -0
- package/templates/plugin-config.json +170 -0
- package/templates/prompt-management-config.json +86 -0
- package/templates/sandbox-config.json +185 -0
- package/templates/schemas-config.json +65 -0
- package/templates/security-config.json +120 -0
- package/templates/skill-marketplace-config.json +441 -0
- package/templates/streaming-config.json +72 -0
- package/templates/testing-config.json +81 -0
- package/templates/timetravel-config.json +62 -0
- package/templates/tool-registry-config.json +109 -0
- package/templates/voice-commands-config.json +658 -0
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: streaming
|
|
3
|
+
description: Sistema de streaming de progreso en tiempo real
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ELSABRO Progress Streaming System
|
|
8
|
+
|
|
9
|
+
## Vision General
|
|
10
|
+
|
|
11
|
+
El sistema de streaming proporciona actualizaciones en tiempo real sobre el progreso de ejecución, permitiendo al usuario ver qué está pasando sin esperar a que termine.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
┌──────────────────────────────────────────────────────────────────────────┐
|
|
15
|
+
│ STREAMING MODES │
|
|
16
|
+
├──────────────────────────────────────────────────────────────────────────┤
|
|
17
|
+
│ │
|
|
18
|
+
│ MODE: VALUES │
|
|
19
|
+
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
20
|
+
│ │ Emite el estado completo después de cada nodo │ │
|
|
21
|
+
│ │ │ │
|
|
22
|
+
│ │ { nodes: { analyze: {...}, implement: {...} }, current: "impl" }│ │
|
|
23
|
+
│ └────────────────────────────────────────────────────────────────┘ │
|
|
24
|
+
│ │
|
|
25
|
+
│ MODE: UPDATES │
|
|
26
|
+
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
27
|
+
│ │ Emite solo los cambios (delta) después de cada operación │ │
|
|
28
|
+
│ │ │ │
|
|
29
|
+
│ │ { type: "node_complete", node: "analyze", output: {...} } │ │
|
|
30
|
+
│ └────────────────────────────────────────────────────────────────┘ │
|
|
31
|
+
│ │
|
|
32
|
+
│ MODE: MESSAGES │
|
|
33
|
+
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
34
|
+
│ │ Emite mensajes de texto legibles para el usuario │ │
|
|
35
|
+
│ │ │ │
|
|
36
|
+
│ │ "✓ Analysis complete - found 3 files to modify" │ │
|
|
37
|
+
│ └────────────────────────────────────────────────────────────────┘ │
|
|
38
|
+
│ │
|
|
39
|
+
└──────────────────────────────────────────────────────────────────────────┘
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Modos de Streaming
|
|
45
|
+
|
|
46
|
+
### 1. Values Mode
|
|
47
|
+
|
|
48
|
+
Emite el estado completo después de cada operación. Útil para debugging y UIs que necesitan el estado completo.
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
// Ejemplo de output en values mode
|
|
52
|
+
{
|
|
53
|
+
"mode": "values",
|
|
54
|
+
"timestamp": "2024-01-20T15:30:45.123Z",
|
|
55
|
+
"state": {
|
|
56
|
+
"flowId": "development_flow",
|
|
57
|
+
"status": "RUNNING",
|
|
58
|
+
"currentNode": "implement",
|
|
59
|
+
"progress": 0.45,
|
|
60
|
+
"nodes": {
|
|
61
|
+
"start": { "status": "COMPLETE", "duration": 50 },
|
|
62
|
+
"analyze": { "status": "COMPLETE", "duration": 15000, "output": {...} },
|
|
63
|
+
"implement": { "status": "RUNNING", "startedAt": "..." }
|
|
64
|
+
},
|
|
65
|
+
"variables": {
|
|
66
|
+
"filesAnalyzed": 12,
|
|
67
|
+
"planCreated": true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Updates Mode
|
|
74
|
+
|
|
75
|
+
Emite solo los cambios (deltas). Más eficiente en ancho de banda y procesamiento.
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
// Ejemplo de outputs en updates mode
|
|
79
|
+
{ "type": "flow_started", "flowId": "development_flow", "at": "..." }
|
|
80
|
+
{ "type": "node_started", "node": "analyze", "at": "..." }
|
|
81
|
+
{ "type": "agent_started", "agent": "Explore", "node": "analyze" }
|
|
82
|
+
{ "type": "agent_complete", "agent": "Explore", "duration": 12000, "output": {...} }
|
|
83
|
+
{ "type": "node_complete", "node": "analyze", "duration": 15000 }
|
|
84
|
+
{ "type": "node_started", "node": "implement", "at": "..." }
|
|
85
|
+
{ "type": "progress", "value": 0.45 }
|
|
86
|
+
{ "type": "variable_set", "key": "filesModified", "value": ["src/auth.ts"] }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 3. Messages Mode
|
|
90
|
+
|
|
91
|
+
Emite mensajes de texto legibles para humanos. Ideal para CLI y logs de usuario.
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
// Ejemplo de outputs en messages mode
|
|
95
|
+
"🚀 Starting flow: development_flow"
|
|
96
|
+
"📊 Phase 1: Analyzing codebase..."
|
|
97
|
+
" ├─ Explore agent: scanning structure"
|
|
98
|
+
" ├─ Plan agent: creating implementation plan"
|
|
99
|
+
" └─ Code-explorer: analyzing existing code"
|
|
100
|
+
"✓ Analysis complete - found 5 files to modify"
|
|
101
|
+
"⚙️ Phase 2: Implementing changes..."
|
|
102
|
+
" ├─ Executor: implementing auth module"
|
|
103
|
+
" └─ QA: writing tests"
|
|
104
|
+
"✓ Implementation complete - 3 files created, 2 modified"
|
|
105
|
+
"🔍 Phase 3: Reviewing code..."
|
|
106
|
+
"✅ Flow complete! Duration: 2m 34s"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## API de Streaming
|
|
112
|
+
|
|
113
|
+
### StreamManager
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
/**
|
|
117
|
+
* StreamManager
|
|
118
|
+
* Gestiona streaming de progreso en tiempo real
|
|
119
|
+
*/
|
|
120
|
+
class StreamManager {
|
|
121
|
+
constructor(options = {}) {
|
|
122
|
+
this.config = {
|
|
123
|
+
mode: options.mode || 'messages', // 'values' | 'updates' | 'messages'
|
|
124
|
+
throttle: options.throttle || 100, // ms entre emisiones
|
|
125
|
+
buffer: options.buffer || true,
|
|
126
|
+
maxBufferSize: options.maxBufferSize || 100
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
this.subscribers = new Set();
|
|
130
|
+
this.buffer = [];
|
|
131
|
+
this.state = {};
|
|
132
|
+
this.lastEmit = 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ==================== Subscription ====================
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Suscribe un listener al stream
|
|
139
|
+
*/
|
|
140
|
+
subscribe(callback) {
|
|
141
|
+
this.subscribers.add(callback);
|
|
142
|
+
|
|
143
|
+
// Retornar función para desuscribir
|
|
144
|
+
return () => {
|
|
145
|
+
this.subscribers.delete(callback);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Emite a todos los suscriptores
|
|
151
|
+
*/
|
|
152
|
+
emit(data) {
|
|
153
|
+
const now = Date.now();
|
|
154
|
+
|
|
155
|
+
// Throttling
|
|
156
|
+
if (this.config.throttle && now - this.lastEmit < this.config.throttle) {
|
|
157
|
+
if (this.config.buffer) {
|
|
158
|
+
this.buffer.push(data);
|
|
159
|
+
if (this.buffer.length > this.config.maxBufferSize) {
|
|
160
|
+
this.buffer.shift();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Flush buffer si hay
|
|
167
|
+
if (this.buffer.length > 0) {
|
|
168
|
+
const buffered = [...this.buffer];
|
|
169
|
+
this.buffer = [];
|
|
170
|
+
|
|
171
|
+
for (const item of buffered) {
|
|
172
|
+
this.emitToSubscribers(item);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
this.emitToSubscribers(data);
|
|
177
|
+
this.lastEmit = now;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
emitToSubscribers(data) {
|
|
181
|
+
for (const callback of this.subscribers) {
|
|
182
|
+
try {
|
|
183
|
+
callback(data);
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error('Stream subscriber error:', error);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ==================== Mode-Specific Emitters ====================
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Emite según el modo configurado
|
|
194
|
+
*/
|
|
195
|
+
emitProgress(event, context = {}) {
|
|
196
|
+
switch (this.config.mode) {
|
|
197
|
+
case 'values':
|
|
198
|
+
this.emitValues(event, context);
|
|
199
|
+
break;
|
|
200
|
+
case 'updates':
|
|
201
|
+
this.emitUpdates(event, context);
|
|
202
|
+
break;
|
|
203
|
+
case 'messages':
|
|
204
|
+
this.emitMessages(event, context);
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Emite estado completo (values mode)
|
|
211
|
+
*/
|
|
212
|
+
emitValues(event, context) {
|
|
213
|
+
// Actualizar estado interno
|
|
214
|
+
this.updateState(event, context);
|
|
215
|
+
|
|
216
|
+
this.emit({
|
|
217
|
+
mode: 'values',
|
|
218
|
+
timestamp: new Date().toISOString(),
|
|
219
|
+
event: event.type,
|
|
220
|
+
state: { ...this.state }
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Emite delta (updates mode)
|
|
226
|
+
*/
|
|
227
|
+
emitUpdates(event, context) {
|
|
228
|
+
this.emit({
|
|
229
|
+
mode: 'updates',
|
|
230
|
+
timestamp: new Date().toISOString(),
|
|
231
|
+
type: event.type,
|
|
232
|
+
...event.data,
|
|
233
|
+
...context
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Emite mensaje legible (messages mode)
|
|
239
|
+
*/
|
|
240
|
+
emitMessages(event, context) {
|
|
241
|
+
const message = this.formatMessage(event, context);
|
|
242
|
+
|
|
243
|
+
if (message) {
|
|
244
|
+
this.emit({
|
|
245
|
+
mode: 'messages',
|
|
246
|
+
timestamp: new Date().toISOString(),
|
|
247
|
+
message
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// También imprimir a consola
|
|
251
|
+
console.log(message);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ==================== State Management ====================
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Actualiza estado interno
|
|
259
|
+
*/
|
|
260
|
+
updateState(event, context) {
|
|
261
|
+
switch (event.type) {
|
|
262
|
+
case 'flow_started':
|
|
263
|
+
this.state = {
|
|
264
|
+
flowId: event.data.flowId,
|
|
265
|
+
status: 'RUNNING',
|
|
266
|
+
startedAt: new Date().toISOString(),
|
|
267
|
+
currentNode: null,
|
|
268
|
+
progress: 0,
|
|
269
|
+
nodes: {},
|
|
270
|
+
variables: {}
|
|
271
|
+
};
|
|
272
|
+
break;
|
|
273
|
+
|
|
274
|
+
case 'node_started':
|
|
275
|
+
this.state.currentNode = event.data.nodeId;
|
|
276
|
+
this.state.nodes[event.data.nodeId] = {
|
|
277
|
+
status: 'RUNNING',
|
|
278
|
+
startedAt: new Date().toISOString()
|
|
279
|
+
};
|
|
280
|
+
break;
|
|
281
|
+
|
|
282
|
+
case 'node_complete':
|
|
283
|
+
if (this.state.nodes[event.data.nodeId]) {
|
|
284
|
+
this.state.nodes[event.data.nodeId].status = 'COMPLETE';
|
|
285
|
+
this.state.nodes[event.data.nodeId].duration = event.data.duration;
|
|
286
|
+
this.state.nodes[event.data.nodeId].output = event.data.output;
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
|
|
290
|
+
case 'progress':
|
|
291
|
+
this.state.progress = event.data.value;
|
|
292
|
+
break;
|
|
293
|
+
|
|
294
|
+
case 'variable_set':
|
|
295
|
+
this.state.variables[event.data.key] = event.data.value;
|
|
296
|
+
break;
|
|
297
|
+
|
|
298
|
+
case 'flow_complete':
|
|
299
|
+
this.state.status = event.data.success ? 'COMPLETE' : 'FAILED';
|
|
300
|
+
this.state.completedAt = new Date().toISOString();
|
|
301
|
+
this.state.result = event.data.result;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ==================== Message Formatting ====================
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Formatea evento como mensaje legible
|
|
310
|
+
*/
|
|
311
|
+
formatMessage(event, context) {
|
|
312
|
+
const icons = {
|
|
313
|
+
flow_started: '🚀',
|
|
314
|
+
flow_complete: '✅',
|
|
315
|
+
flow_failed: '❌',
|
|
316
|
+
node_started: '⚙️',
|
|
317
|
+
node_complete: '✓',
|
|
318
|
+
agent_started: ' ├─',
|
|
319
|
+
agent_complete: ' ├─',
|
|
320
|
+
progress: '📊',
|
|
321
|
+
checkpoint: '💾',
|
|
322
|
+
interrupt: '⏸️',
|
|
323
|
+
error: '⚠️',
|
|
324
|
+
warning: '⚡'
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
const icon = icons[event.type] || '•';
|
|
328
|
+
|
|
329
|
+
switch (event.type) {
|
|
330
|
+
case 'flow_started':
|
|
331
|
+
return `${icon} Starting flow: ${event.data.flowId}`;
|
|
332
|
+
|
|
333
|
+
case 'flow_complete':
|
|
334
|
+
const duration = this.formatDuration(event.data.duration);
|
|
335
|
+
return event.data.success
|
|
336
|
+
? `${icon} Flow complete! Duration: ${duration}`
|
|
337
|
+
: `❌ Flow failed after ${duration}`;
|
|
338
|
+
|
|
339
|
+
case 'node_started':
|
|
340
|
+
return `${icon} Phase: ${this.formatNodeName(event.data.nodeId)}...`;
|
|
341
|
+
|
|
342
|
+
case 'node_complete':
|
|
343
|
+
const nodeDuration = this.formatDuration(event.data.duration);
|
|
344
|
+
return `${icon} ${this.formatNodeName(event.data.nodeId)} complete (${nodeDuration})`;
|
|
345
|
+
|
|
346
|
+
case 'agent_started':
|
|
347
|
+
return `${icon} ${event.data.agent}: ${event.data.task || 'executing'}`;
|
|
348
|
+
|
|
349
|
+
case 'agent_complete':
|
|
350
|
+
const agentInfo = event.data.filesModified
|
|
351
|
+
? `modified ${event.data.filesModified.length} files`
|
|
352
|
+
: 'done';
|
|
353
|
+
return `${icon} ${event.data.agent}: ${agentInfo}`;
|
|
354
|
+
|
|
355
|
+
case 'progress':
|
|
356
|
+
const percent = Math.round(event.data.value * 100);
|
|
357
|
+
const bar = this.renderProgressBar(event.data.value);
|
|
358
|
+
return `${icon} Progress: ${bar} ${percent}%`;
|
|
359
|
+
|
|
360
|
+
case 'checkpoint':
|
|
361
|
+
return `${icon} Checkpoint saved: ${event.data.checkpointId}`;
|
|
362
|
+
|
|
363
|
+
case 'interrupt':
|
|
364
|
+
return `${icon} Waiting for input: ${event.data.reason}`;
|
|
365
|
+
|
|
366
|
+
case 'error':
|
|
367
|
+
return `${icon} Error: ${event.data.message}`;
|
|
368
|
+
|
|
369
|
+
case 'parallel_started':
|
|
370
|
+
const agents = event.data.agents.join(', ');
|
|
371
|
+
return `${icon} Running ${event.data.agents.length} agents in parallel: ${agents}`;
|
|
372
|
+
|
|
373
|
+
case 'parallel_complete':
|
|
374
|
+
return `${icon} Parallel execution complete (${event.data.successful}/${event.data.total} succeeded)`;
|
|
375
|
+
|
|
376
|
+
default:
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Formatea duración en formato legible
|
|
383
|
+
*/
|
|
384
|
+
formatDuration(ms) {
|
|
385
|
+
if (ms < 1000) return `${ms}ms`;
|
|
386
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
|
|
387
|
+
const minutes = Math.floor(ms / 60000);
|
|
388
|
+
const seconds = Math.round((ms % 60000) / 1000);
|
|
389
|
+
return `${minutes}m ${seconds}s`;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Formatea nombre de nodo para display
|
|
394
|
+
*/
|
|
395
|
+
formatNodeName(nodeId) {
|
|
396
|
+
return nodeId
|
|
397
|
+
.replace(/_/g, ' ')
|
|
398
|
+
.replace(/\b\w/g, c => c.toUpperCase());
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Renderiza barra de progreso ASCII
|
|
403
|
+
*/
|
|
404
|
+
renderProgressBar(value, width = 20) {
|
|
405
|
+
const filled = Math.round(value * width);
|
|
406
|
+
const empty = width - filled;
|
|
407
|
+
return `[${'█'.repeat(filled)}${'░'.repeat(empty)}]`;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// ==================== High-Level Events ====================
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Flow started
|
|
414
|
+
*/
|
|
415
|
+
flowStarted(flowId, inputs = {}) {
|
|
416
|
+
this.emitProgress({
|
|
417
|
+
type: 'flow_started',
|
|
418
|
+
data: { flowId, inputs }
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Flow completed
|
|
424
|
+
*/
|
|
425
|
+
flowComplete(success, result = {}) {
|
|
426
|
+
const duration = this.state.startedAt
|
|
427
|
+
? Date.now() - new Date(this.state.startedAt).getTime()
|
|
428
|
+
: 0;
|
|
429
|
+
|
|
430
|
+
this.emitProgress({
|
|
431
|
+
type: 'flow_complete',
|
|
432
|
+
data: { success, result, duration }
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Node started
|
|
438
|
+
*/
|
|
439
|
+
nodeStarted(nodeId, nodeType) {
|
|
440
|
+
this.emitProgress({
|
|
441
|
+
type: 'node_started',
|
|
442
|
+
data: { nodeId, nodeType }
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Node completed
|
|
448
|
+
*/
|
|
449
|
+
nodeComplete(nodeId, output, duration) {
|
|
450
|
+
this.emitProgress({
|
|
451
|
+
type: 'node_complete',
|
|
452
|
+
data: { nodeId, output, duration }
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Agent started
|
|
458
|
+
*/
|
|
459
|
+
agentStarted(agent, task) {
|
|
460
|
+
this.emitProgress({
|
|
461
|
+
type: 'agent_started',
|
|
462
|
+
data: { agent, task }
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Agent completed
|
|
468
|
+
*/
|
|
469
|
+
agentComplete(agent, result) {
|
|
470
|
+
this.emitProgress({
|
|
471
|
+
type: 'agent_complete',
|
|
472
|
+
data: {
|
|
473
|
+
agent,
|
|
474
|
+
success: result.success,
|
|
475
|
+
filesModified: result.filesModified,
|
|
476
|
+
duration: result.duration
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Progress update
|
|
483
|
+
*/
|
|
484
|
+
progress(value) {
|
|
485
|
+
this.emitProgress({
|
|
486
|
+
type: 'progress',
|
|
487
|
+
data: { value }
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Parallel execution started
|
|
493
|
+
*/
|
|
494
|
+
parallelStarted(agents) {
|
|
495
|
+
this.emitProgress({
|
|
496
|
+
type: 'parallel_started',
|
|
497
|
+
data: { agents }
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Parallel execution completed
|
|
503
|
+
*/
|
|
504
|
+
parallelComplete(results) {
|
|
505
|
+
const successful = results.filter(r => r.success).length;
|
|
506
|
+
this.emitProgress({
|
|
507
|
+
type: 'parallel_complete',
|
|
508
|
+
data: {
|
|
509
|
+
total: results.length,
|
|
510
|
+
successful,
|
|
511
|
+
failed: results.length - successful
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Checkpoint saved
|
|
518
|
+
*/
|
|
519
|
+
checkpointSaved(checkpointId) {
|
|
520
|
+
this.emitProgress({
|
|
521
|
+
type: 'checkpoint',
|
|
522
|
+
data: { checkpointId }
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Interrupt triggered
|
|
528
|
+
*/
|
|
529
|
+
interruptTriggered(interruptId, reason) {
|
|
530
|
+
this.emitProgress({
|
|
531
|
+
type: 'interrupt',
|
|
532
|
+
data: { interruptId, reason }
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Error occurred
|
|
538
|
+
*/
|
|
539
|
+
error(message, details = {}) {
|
|
540
|
+
this.emitProgress({
|
|
541
|
+
type: 'error',
|
|
542
|
+
data: { message, ...details }
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Singleton instance
|
|
548
|
+
let streamInstance = null;
|
|
549
|
+
|
|
550
|
+
function getStream(options) {
|
|
551
|
+
if (!streamInstance) {
|
|
552
|
+
streamInstance = new StreamManager(options);
|
|
553
|
+
}
|
|
554
|
+
return streamInstance;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
module.exports = { StreamManager, getStream };
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
## Integración con Flow Engine
|
|
563
|
+
|
|
564
|
+
### Instrumentación Automática
|
|
565
|
+
|
|
566
|
+
```javascript
|
|
567
|
+
// En FlowEngine
|
|
568
|
+
class FlowEngine {
|
|
569
|
+
constructor(options = {}) {
|
|
570
|
+
// ...existing code...
|
|
571
|
+
this.stream = options.stream || getStream({ mode: 'messages' });
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
async execute(inputs) {
|
|
575
|
+
this.stream.flowStarted(this.flow.id, inputs);
|
|
576
|
+
|
|
577
|
+
try {
|
|
578
|
+
const result = await this.runFlow(inputs);
|
|
579
|
+
this.stream.flowComplete(true, result);
|
|
580
|
+
return result;
|
|
581
|
+
} catch (error) {
|
|
582
|
+
this.stream.error(error.message);
|
|
583
|
+
this.stream.flowComplete(false, { error: error.message });
|
|
584
|
+
throw error;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
async executeNode(node) {
|
|
589
|
+
this.stream.nodeStarted(node.id, node.type);
|
|
590
|
+
const startTime = Date.now();
|
|
591
|
+
|
|
592
|
+
try {
|
|
593
|
+
const result = await this.executeByType(node);
|
|
594
|
+
const duration = Date.now() - startTime;
|
|
595
|
+
this.stream.nodeComplete(node.id, result, duration);
|
|
596
|
+
return result;
|
|
597
|
+
} catch (error) {
|
|
598
|
+
this.stream.error(`Node ${node.id} failed: ${error.message}`);
|
|
599
|
+
throw error;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
async executeParallelNode(node) {
|
|
604
|
+
const agents = node.branches.map(b => b.agent);
|
|
605
|
+
this.stream.parallelStarted(agents);
|
|
606
|
+
|
|
607
|
+
const results = await Promise.all(
|
|
608
|
+
node.branches.map(branch => this.executeBranch(branch))
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
this.stream.parallelComplete(results);
|
|
612
|
+
return results;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## Display Formats
|
|
620
|
+
|
|
621
|
+
### Live Progress Display
|
|
622
|
+
|
|
623
|
+
```
|
|
624
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
625
|
+
║ ELSABRO - Flow Execution ║
|
|
626
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
627
|
+
║ Flow: development_flow ║
|
|
628
|
+
║ Status: RUNNING ║
|
|
629
|
+
║ Progress: [████████████░░░░░░░░] 60% ║
|
|
630
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
631
|
+
║ ║
|
|
632
|
+
║ 🚀 Starting flow: development_flow ║
|
|
633
|
+
║ ⚙️ Phase: Analyze... ║
|
|
634
|
+
║ ├─ Explore: scanning structure ║
|
|
635
|
+
║ ├─ Plan: creating implementation plan ║
|
|
636
|
+
║ ├─ Code-explorer: analyzing existing code ║
|
|
637
|
+
║ └─ General-purpose: checking tech debt ║
|
|
638
|
+
║ ✓ Analyze complete (15.2s) ║
|
|
639
|
+
║ ⚙️ Phase: Implement... ║
|
|
640
|
+
║ ├─ Executor: implementing auth module ║
|
|
641
|
+
║ └─ QA: writing tests ║
|
|
642
|
+
║ ⏳ Waiting for implementation... ║
|
|
643
|
+
║ ║
|
|
644
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### Compact Progress
|
|
648
|
+
|
|
649
|
+
```
|
|
650
|
+
development_flow [████████████░░░░░░░░] 60% - Implementing auth module
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
## Comandos de Usuario
|
|
656
|
+
|
|
657
|
+
### /elsabro:stream
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
/elsabro:stream mode values # Cambiar a modo values
|
|
661
|
+
/elsabro:stream mode updates # Cambiar a modo updates
|
|
662
|
+
/elsabro:stream mode messages # Cambiar a modo messages (default)
|
|
663
|
+
/elsabro:stream pause # Pausar streaming
|
|
664
|
+
/elsabro:stream resume # Resumir streaming
|
|
665
|
+
/elsabro:stream history # Ver historial de mensajes
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
670
|
+
## Configuración
|
|
671
|
+
|
|
672
|
+
### .planning/streaming-config.json
|
|
673
|
+
|
|
674
|
+
```json
|
|
675
|
+
{
|
|
676
|
+
"streaming": {
|
|
677
|
+
"enabled": true,
|
|
678
|
+
"mode": "messages",
|
|
679
|
+
"throttle": 100,
|
|
680
|
+
"buffer": true,
|
|
681
|
+
"maxBufferSize": 100,
|
|
682
|
+
"display": {
|
|
683
|
+
"showProgress": true,
|
|
684
|
+
"showAgents": true,
|
|
685
|
+
"showTimestamps": false,
|
|
686
|
+
"progressBarWidth": 20,
|
|
687
|
+
"colorize": true
|
|
688
|
+
},
|
|
689
|
+
"subscribers": {
|
|
690
|
+
"console": true,
|
|
691
|
+
"file": false,
|
|
692
|
+
"websocket": false
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
```
|