flock-core 0.5.0b70__py3-none-any.whl → 0.5.0b75__py3-none-any.whl
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.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/agent.py +39 -1
- flock/artifacts.py +17 -10
- flock/cli.py +1 -1
- flock/dashboard/__init__.py +2 -0
- flock/dashboard/collector.py +282 -6
- flock/dashboard/events.py +6 -0
- flock/dashboard/graph_builder.py +563 -0
- flock/dashboard/launcher.py +11 -6
- flock/dashboard/models/graph.py +156 -0
- flock/dashboard/service.py +175 -14
- flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
- flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
- flock/dashboard/static_v2/index.html +13 -0
- flock/dashboard/websocket.py +2 -2
- flock/engines/dspy_engine.py +28 -9
- flock/frontend/README.md +6 -6
- flock/frontend/src/App.tsx +23 -31
- flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
- flock/frontend/src/components/details/DetailWindowContainer.tsx +13 -17
- flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
- flock/frontend/src/components/details/MessageHistoryTab.tsx +128 -53
- flock/frontend/src/components/details/RunStatusTab.tsx +79 -38
- flock/frontend/src/components/graph/AgentNode.test.tsx +3 -1
- flock/frontend/src/components/graph/AgentNode.tsx +8 -6
- flock/frontend/src/components/graph/GraphCanvas.tsx +13 -8
- flock/frontend/src/components/graph/MessageNode.test.tsx +3 -1
- flock/frontend/src/components/graph/MessageNode.tsx +16 -3
- flock/frontend/src/components/layout/DashboardLayout.tsx +12 -9
- flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +4 -14
- flock/frontend/src/components/modules/ModuleRegistry.ts +5 -3
- flock/frontend/src/hooks/useModules.ts +12 -4
- flock/frontend/src/hooks/usePersistence.ts +5 -3
- flock/frontend/src/services/api.ts +3 -19
- flock/frontend/src/services/graphService.test.ts +330 -0
- flock/frontend/src/services/graphService.ts +75 -0
- flock/frontend/src/services/websocket.ts +104 -268
- flock/frontend/src/store/filterStore.test.ts +89 -1
- flock/frontend/src/store/filterStore.ts +38 -16
- flock/frontend/src/store/graphStore.test.ts +538 -173
- flock/frontend/src/store/graphStore.ts +374 -465
- flock/frontend/src/store/moduleStore.ts +51 -33
- flock/frontend/src/store/uiStore.ts +23 -11
- flock/frontend/src/types/graph.ts +77 -44
- flock/frontend/src/utils/mockData.ts +16 -3
- flock/frontend/vite.config.ts +2 -2
- flock/orchestrator.py +24 -6
- flock/service.py +2 -2
- flock/store.py +169 -4
- flock/themes/darkmatrix.toml +2 -2
- flock/themes/deep.toml +2 -2
- flock/themes/neopolitan.toml +4 -4
- {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/METADATA +1 -1
- {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/RECORD +56 -53
- flock/frontend/src/__tests__/e2e/critical-scenarios.test.tsx +0 -586
- flock/frontend/src/__tests__/integration/filtering-e2e.test.tsx +0 -391
- flock/frontend/src/__tests__/integration/graph-rendering.test.tsx +0 -640
- flock/frontend/src/services/websocket.test.ts +0 -595
- flock/frontend/src/utils/transforms.test.ts +0 -860
- flock/frontend/src/utils/transforms.ts +0 -323
- {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/WHEEL +0 -0
- {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/entry_points.txt +0 -0
- {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import { Edge } from '@xyflow/react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Phase 4: Graph Visualization & Dual Views - Edge Derivation Algorithms
|
|
5
|
-
*
|
|
6
|
-
* Implements edge derivation logic as specified in DATA_MODEL.md:
|
|
7
|
-
* - deriveAgentViewEdges: Creates message flow edges between agents (producer → consumer)
|
|
8
|
-
* - deriveBlackboardViewEdges: Creates transformation edges between artifacts (consumed → produced)
|
|
9
|
-
*
|
|
10
|
-
* SPECIFICATION: docs/specs/003-real-time-dashboard/DATA_MODEL.md lines 770-853
|
|
11
|
-
* REFERENCE: docs/specs/003-real-time-dashboard/PLAN.md Phase 4
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// Type definitions matching DATA_MODEL.md specification
|
|
15
|
-
export interface Artifact {
|
|
16
|
-
artifact_id: string;
|
|
17
|
-
artifact_type: string;
|
|
18
|
-
produced_by: string;
|
|
19
|
-
consumed_by: string[];
|
|
20
|
-
published_at: string; // ISO timestamp
|
|
21
|
-
payload: any;
|
|
22
|
-
correlation_id: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface Run {
|
|
26
|
-
run_id: string;
|
|
27
|
-
agent_name: string;
|
|
28
|
-
correlation_id: string; // Groups multiple agent runs together
|
|
29
|
-
status: 'active' | 'completed' | 'error';
|
|
30
|
-
consumed_artifacts: string[];
|
|
31
|
-
produced_artifacts: string[];
|
|
32
|
-
duration_ms?: number;
|
|
33
|
-
started_at?: string;
|
|
34
|
-
completed_at?: string;
|
|
35
|
-
metrics?: {
|
|
36
|
-
tokensUsed?: number;
|
|
37
|
-
costUsd?: number;
|
|
38
|
-
artifactsProduced?: number;
|
|
39
|
-
};
|
|
40
|
-
error_message?: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface DashboardState {
|
|
44
|
-
artifacts: Map<string, Artifact>;
|
|
45
|
-
runs: Map<string, Run>;
|
|
46
|
-
consumptions: Map<string, string[]>; // Phase 11: Track actual consumption (artifact_id -> consumer_ids[])
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Edge type definitions from DATA_MODEL.md
|
|
50
|
-
// Note: Using camelCase for TypeScript/JavaScript convention
|
|
51
|
-
export interface AgentViewEdge extends Edge {
|
|
52
|
-
type: 'message_flow';
|
|
53
|
-
label: string; // Format: "messageType (count)"
|
|
54
|
-
data: {
|
|
55
|
-
messageType: string;
|
|
56
|
-
messageCount: number;
|
|
57
|
-
artifactIds: string[];
|
|
58
|
-
latestTimestamp: string;
|
|
59
|
-
labelOffset?: number; // Phase 11: Vertical offset in pixels to prevent label overlap
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface BlackboardViewEdge extends Edge {
|
|
64
|
-
type: 'transformation';
|
|
65
|
-
label: string; // agentName
|
|
66
|
-
data: {
|
|
67
|
-
transformerAgent: string;
|
|
68
|
-
runId: string;
|
|
69
|
-
durationMs?: number;
|
|
70
|
-
labelOffset?: number; // Phase 11: Vertical offset in pixels to prevent label overlap
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Derive Agent View edges from dashboard state
|
|
76
|
-
*
|
|
77
|
-
* Algorithm (DATA_MODEL.md lines 770-821):
|
|
78
|
-
* 1. Group messages by (producer, consumer, message_type)
|
|
79
|
-
* 2. Create one edge per unique triple
|
|
80
|
-
* 3. Count artifacts in each group
|
|
81
|
-
* 4. Track latest timestamp
|
|
82
|
-
* 5. Add label offset for multiple edges between same nodes (Phase 11 bug fix)
|
|
83
|
-
*
|
|
84
|
-
* Edge format:
|
|
85
|
-
* - ID: `${producer}_${consumer}_${message_type}`
|
|
86
|
-
* - Type: 'message_flow'
|
|
87
|
-
* - Label: "Type (N)" where N is the count
|
|
88
|
-
* - Data: { message_type, message_count, artifact_ids[], latest_timestamp, labelOffset }
|
|
89
|
-
*
|
|
90
|
-
* @param state - Dashboard state with artifacts and runs
|
|
91
|
-
* @returns Array of message flow edges
|
|
92
|
-
*/
|
|
93
|
-
export function deriveAgentViewEdges(state: DashboardState): AgentViewEdge[] {
|
|
94
|
-
const edgeMap = new Map<
|
|
95
|
-
string,
|
|
96
|
-
{
|
|
97
|
-
source: string;
|
|
98
|
-
target: string;
|
|
99
|
-
message_type: string;
|
|
100
|
-
artifact_ids: string[];
|
|
101
|
-
latest_timestamp: string;
|
|
102
|
-
}
|
|
103
|
-
>();
|
|
104
|
-
|
|
105
|
-
// Iterate through all artifacts
|
|
106
|
-
state.artifacts.forEach((artifact) => {
|
|
107
|
-
const producer = artifact.produced_by;
|
|
108
|
-
const messageType = artifact.artifact_type;
|
|
109
|
-
|
|
110
|
-
// For each consumer, create or update edge
|
|
111
|
-
artifact.consumed_by.forEach((consumer) => {
|
|
112
|
-
const edgeKey = `${producer}_${consumer}_${messageType}`;
|
|
113
|
-
|
|
114
|
-
const existing = edgeMap.get(edgeKey);
|
|
115
|
-
|
|
116
|
-
if (existing) {
|
|
117
|
-
// Update existing edge
|
|
118
|
-
existing.artifact_ids.push(artifact.artifact_id);
|
|
119
|
-
|
|
120
|
-
// Update latest timestamp if this artifact is newer
|
|
121
|
-
if (artifact.published_at > existing.latest_timestamp) {
|
|
122
|
-
existing.latest_timestamp = artifact.published_at;
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
// Create new edge entry
|
|
126
|
-
edgeMap.set(edgeKey, {
|
|
127
|
-
source: producer,
|
|
128
|
-
target: consumer,
|
|
129
|
-
message_type: messageType,
|
|
130
|
-
artifact_ids: [artifact.artifact_id],
|
|
131
|
-
latest_timestamp: artifact.published_at,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// Phase 11 Bug Fix: Calculate label offsets for edges between same node pairs
|
|
138
|
-
// Group edges by node pair to detect multiple edges
|
|
139
|
-
// Use canonical pair key (sorted) so A→B and B→A are treated as same pair
|
|
140
|
-
const nodePairEdges = new Map<string, string[]>();
|
|
141
|
-
edgeMap.forEach((data, edgeKey) => {
|
|
142
|
-
const nodes = [data.source, data.target].sort();
|
|
143
|
-
const pairKey = `${nodes[0]}_${nodes[1]}`;
|
|
144
|
-
const existing = nodePairEdges.get(pairKey) || [];
|
|
145
|
-
existing.push(edgeKey);
|
|
146
|
-
nodePairEdges.set(pairKey, existing);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// Convert map to edges with label offsets
|
|
150
|
-
const edges: AgentViewEdge[] = [];
|
|
151
|
-
|
|
152
|
-
edgeMap.forEach((data, edgeKey) => {
|
|
153
|
-
const nodes = [data.source, data.target].sort();
|
|
154
|
-
const pairKey = `${nodes[0]}_${nodes[1]}`;
|
|
155
|
-
const edgesInPair = nodePairEdges.get(pairKey) || [];
|
|
156
|
-
const edgeIndex = edgesInPair.indexOf(edgeKey);
|
|
157
|
-
const totalEdgesInPair = edgesInPair.length;
|
|
158
|
-
|
|
159
|
-
// Calculate label offset (spread labels vertically if multiple edges)
|
|
160
|
-
// Offset range: -20 to +20 pixels for up to 3 edges, more if needed
|
|
161
|
-
let labelOffset = 0;
|
|
162
|
-
if (totalEdgesInPair > 1) {
|
|
163
|
-
const offsetRange = Math.min(40, totalEdgesInPair * 15);
|
|
164
|
-
const step = offsetRange / (totalEdgesInPair - 1);
|
|
165
|
-
labelOffset = edgeIndex * step - offsetRange / 2;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Phase 11 Bug Fix: Calculate filtered count from actual consumption data
|
|
169
|
-
// Count how many artifacts were actually consumed by the target agent
|
|
170
|
-
const totalCount = data.artifact_ids.length;
|
|
171
|
-
const consumedCount = data.artifact_ids.filter((artifactId) => {
|
|
172
|
-
const consumers = state.consumptions.get(artifactId) || [];
|
|
173
|
-
return consumers.includes(data.target);
|
|
174
|
-
}).length;
|
|
175
|
-
|
|
176
|
-
// Format label: "Type (total, filtered: consumed)" if filtering occurred
|
|
177
|
-
let label = `${data.message_type} (${totalCount})`;
|
|
178
|
-
if (consumedCount < totalCount && consumedCount > 0) {
|
|
179
|
-
label = `${data.message_type} (${totalCount}, filtered: ${consumedCount})`;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
edges.push({
|
|
183
|
-
id: edgeKey,
|
|
184
|
-
source: data.source,
|
|
185
|
-
target: data.target,
|
|
186
|
-
type: 'message_flow',
|
|
187
|
-
label,
|
|
188
|
-
markerEnd: {
|
|
189
|
-
type: 'arrowclosed',
|
|
190
|
-
width: 20,
|
|
191
|
-
height: 20,
|
|
192
|
-
},
|
|
193
|
-
data: {
|
|
194
|
-
messageType: data.message_type,
|
|
195
|
-
messageCount: data.artifact_ids.length,
|
|
196
|
-
artifactIds: data.artifact_ids,
|
|
197
|
-
latestTimestamp: data.latest_timestamp,
|
|
198
|
-
labelOffset, // Phase 11: Added for label positioning
|
|
199
|
-
},
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
return edges;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Derive Blackboard View edges from dashboard state
|
|
208
|
-
*
|
|
209
|
-
* Algorithm (DATA_MODEL.md lines 824-853):
|
|
210
|
-
* 1. For each completed run (status !== 'active')
|
|
211
|
-
* 2. Create edges from consumed artifacts to produced artifacts
|
|
212
|
-
* 3. Label with agent name
|
|
213
|
-
* 4. Include run metadata (run_id, duration_ms)
|
|
214
|
-
* 5. Add label offset for multiple edges between same artifacts (Phase 11 bug fix)
|
|
215
|
-
*
|
|
216
|
-
* Edge format:
|
|
217
|
-
* - ID: `${consumed_id}_${produced_id}_${run_id}` (Phase 11: Added run_id for uniqueness)
|
|
218
|
-
* - Type: 'transformation'
|
|
219
|
-
* - Label: agent_name
|
|
220
|
-
* - Data: { transformer_agent, run_id, duration_ms, labelOffset }
|
|
221
|
-
*
|
|
222
|
-
* @param state - Dashboard state with artifacts and runs
|
|
223
|
-
* @returns Array of transformation edges
|
|
224
|
-
*/
|
|
225
|
-
export function deriveBlackboardViewEdges(
|
|
226
|
-
state: DashboardState
|
|
227
|
-
): BlackboardViewEdge[] {
|
|
228
|
-
const tempEdges: Array<{
|
|
229
|
-
id: string;
|
|
230
|
-
source: string;
|
|
231
|
-
target: string;
|
|
232
|
-
label: string;
|
|
233
|
-
data: {
|
|
234
|
-
transformerAgent: string;
|
|
235
|
-
runId: string;
|
|
236
|
-
durationMs?: number;
|
|
237
|
-
};
|
|
238
|
-
}> = [];
|
|
239
|
-
|
|
240
|
-
// Iterate through all runs
|
|
241
|
-
state.runs.forEach((run) => {
|
|
242
|
-
// Skip active runs (only process completed or error runs)
|
|
243
|
-
if (run.status === 'active') {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Skip runs with no consumed or produced artifacts
|
|
248
|
-
if (
|
|
249
|
-
run.consumed_artifacts.length === 0 ||
|
|
250
|
-
run.produced_artifacts.length === 0
|
|
251
|
-
) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Create edges for each consumed × produced pair
|
|
256
|
-
run.consumed_artifacts.forEach((consumedId) => {
|
|
257
|
-
run.produced_artifacts.forEach((producedId) => {
|
|
258
|
-
// Phase 11: Include run_id in edge ID to make it unique per transformation
|
|
259
|
-
const edgeId = `${consumedId}_${producedId}_${run.run_id}`;
|
|
260
|
-
|
|
261
|
-
tempEdges.push({
|
|
262
|
-
id: edgeId,
|
|
263
|
-
source: consumedId,
|
|
264
|
-
target: producedId,
|
|
265
|
-
label: run.agent_name,
|
|
266
|
-
data: {
|
|
267
|
-
transformerAgent: run.agent_name,
|
|
268
|
-
runId: run.run_id,
|
|
269
|
-
durationMs: run.duration_ms,
|
|
270
|
-
},
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
// Phase 11 Bug Fix: Calculate label offsets for edges between same artifact pairs
|
|
277
|
-
// Group edges by artifact pair to detect multiple transformations
|
|
278
|
-
// Use canonical pair key (sorted) so A→B and B→A are treated as same pair
|
|
279
|
-
const artifactPairEdges = new Map<string, string[]>();
|
|
280
|
-
tempEdges.forEach((edge) => {
|
|
281
|
-
const nodes = [edge.source, edge.target].sort();
|
|
282
|
-
const pairKey = `${nodes[0]}_${nodes[1]}`;
|
|
283
|
-
const existing = artifactPairEdges.get(pairKey) || [];
|
|
284
|
-
existing.push(edge.id);
|
|
285
|
-
artifactPairEdges.set(pairKey, existing);
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
// Convert to final edges with label offsets
|
|
289
|
-
const edges: BlackboardViewEdge[] = tempEdges.map((edge) => {
|
|
290
|
-
const nodes = [edge.source, edge.target].sort();
|
|
291
|
-
const pairKey = `${nodes[0]}_${nodes[1]}`;
|
|
292
|
-
const edgesInPair = artifactPairEdges.get(pairKey) || [];
|
|
293
|
-
const edgeIndex = edgesInPair.indexOf(edge.id);
|
|
294
|
-
const totalEdgesInPair = edgesInPair.length;
|
|
295
|
-
|
|
296
|
-
// Calculate label offset (spread labels vertically if multiple transformations)
|
|
297
|
-
let labelOffset = 0;
|
|
298
|
-
if (totalEdgesInPair > 1) {
|
|
299
|
-
const offsetRange = Math.min(40, totalEdgesInPair * 15);
|
|
300
|
-
const step = offsetRange / (totalEdgesInPair - 1);
|
|
301
|
-
labelOffset = edgeIndex * step - offsetRange / 2;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return {
|
|
305
|
-
id: edge.id,
|
|
306
|
-
source: edge.source,
|
|
307
|
-
target: edge.target,
|
|
308
|
-
type: 'transformation',
|
|
309
|
-
label: edge.label,
|
|
310
|
-
markerEnd: {
|
|
311
|
-
type: 'arrowclosed',
|
|
312
|
-
width: 20,
|
|
313
|
-
height: 20,
|
|
314
|
-
},
|
|
315
|
-
data: {
|
|
316
|
-
...edge.data,
|
|
317
|
-
labelOffset, // Phase 11: Added for label positioning
|
|
318
|
-
},
|
|
319
|
-
};
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
return edges;
|
|
323
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|