flock-core 0.5.5__py3-none-any.whl → 0.5.7__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 +141 -17
- flock/components.py +4 -0
- flock/dashboard/collector.py +2 -0
- flock/orchestrator.py +386 -155
- flock/orchestrator_component.py +686 -0
- {flock_core-0.5.5.dist-info → flock_core-0.5.7.dist-info}/METADATA +69 -5
- {flock_core-0.5.5.dist-info → flock_core-0.5.7.dist-info}/RECORD +10 -9
- {flock_core-0.5.5.dist-info → flock_core-0.5.7.dist-info}/WHEEL +0 -0
- {flock_core-0.5.5.dist-info → flock_core-0.5.7.dist-info}/entry_points.txt +0 -0
- {flock_core-0.5.5.dist-info → flock_core-0.5.7.dist-info}/licenses/LICENSE +0 -0
flock/agent.py
CHANGED
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import os
|
|
7
|
+
from collections.abc import Sequence
|
|
7
8
|
from dataclasses import dataclass
|
|
8
9
|
from typing import TYPE_CHECKING, Any, TypedDict
|
|
9
10
|
|
|
@@ -118,6 +119,31 @@ class Agent(metaclass=AutoTracedMeta):
|
|
|
118
119
|
def identity(self) -> AgentIdentity:
|
|
119
120
|
return AgentIdentity(name=self.name, labels=self.labels, tenant_id=self.tenant_id)
|
|
120
121
|
|
|
122
|
+
@staticmethod
|
|
123
|
+
def _component_display_name(component: AgentComponent) -> str:
|
|
124
|
+
return component.name or component.__class__.__name__
|
|
125
|
+
|
|
126
|
+
def _sorted_utilities(self) -> list[AgentComponent]:
|
|
127
|
+
if not self.utilities:
|
|
128
|
+
return []
|
|
129
|
+
return sorted(self.utilities, key=lambda comp: getattr(comp, "priority", 0))
|
|
130
|
+
|
|
131
|
+
def _add_utilities(self, components: Sequence[AgentComponent]) -> None:
|
|
132
|
+
if not components:
|
|
133
|
+
return
|
|
134
|
+
for component in components:
|
|
135
|
+
self.utilities.append(component)
|
|
136
|
+
comp_name = self._component_display_name(component)
|
|
137
|
+
priority = getattr(component, "priority", 0)
|
|
138
|
+
logger.info(
|
|
139
|
+
"Agent %s: utility added: component=%s, priority=%s, total_utilities=%s",
|
|
140
|
+
self.name,
|
|
141
|
+
comp_name,
|
|
142
|
+
priority,
|
|
143
|
+
len(self.utilities),
|
|
144
|
+
)
|
|
145
|
+
self.utilities.sort(key=lambda comp: getattr(comp, "priority", 0))
|
|
146
|
+
|
|
121
147
|
def set_max_concurrency(self, value: int) -> None:
|
|
122
148
|
self.max_concurrency = max(1, value)
|
|
123
149
|
self._semaphore = asyncio.Semaphore(self.max_concurrency)
|
|
@@ -221,21 +247,59 @@ class Agent(metaclass=AutoTracedMeta):
|
|
|
221
247
|
return []
|
|
222
248
|
|
|
223
249
|
async def _run_initialize(self, ctx: Context) -> None:
|
|
224
|
-
for component in self.
|
|
225
|
-
|
|
250
|
+
for component in self._sorted_utilities():
|
|
251
|
+
comp_name = self._component_display_name(component)
|
|
252
|
+
priority = getattr(component, "priority", 0)
|
|
253
|
+
logger.debug(
|
|
254
|
+
f"Agent initialize: agent={self.name}, component={comp_name}, priority={priority}"
|
|
255
|
+
)
|
|
256
|
+
try:
|
|
257
|
+
await component.on_initialize(self, ctx)
|
|
258
|
+
except Exception as exc:
|
|
259
|
+
logger.exception(
|
|
260
|
+
f"Agent initialize failed: agent={self.name}, component={comp_name}, "
|
|
261
|
+
f"priority={priority}, error={exc!s}"
|
|
262
|
+
)
|
|
263
|
+
raise
|
|
226
264
|
for engine in self.engines:
|
|
227
265
|
await engine.on_initialize(self, ctx)
|
|
228
266
|
|
|
229
267
|
async def _run_pre_consume(self, ctx: Context, inputs: list[Artifact]) -> list[Artifact]:
|
|
230
268
|
current = inputs
|
|
231
|
-
for component in self.
|
|
232
|
-
|
|
269
|
+
for component in self._sorted_utilities():
|
|
270
|
+
comp_name = self._component_display_name(component)
|
|
271
|
+
priority = getattr(component, "priority", 0)
|
|
272
|
+
logger.debug(
|
|
273
|
+
f"Agent pre_consume: agent={self.name}, component={comp_name}, "
|
|
274
|
+
f"priority={priority}, input_count={len(current)}"
|
|
275
|
+
)
|
|
276
|
+
try:
|
|
277
|
+
current = await component.on_pre_consume(self, ctx, current)
|
|
278
|
+
except Exception as exc:
|
|
279
|
+
logger.exception(
|
|
280
|
+
f"Agent pre_consume failed: agent={self.name}, component={comp_name}, "
|
|
281
|
+
f"priority={priority}, error={exc!s}"
|
|
282
|
+
)
|
|
283
|
+
raise
|
|
233
284
|
return current
|
|
234
285
|
|
|
235
286
|
async def _run_pre_evaluate(self, ctx: Context, inputs: EvalInputs) -> EvalInputs:
|
|
236
287
|
current = inputs
|
|
237
|
-
for component in self.
|
|
238
|
-
|
|
288
|
+
for component in self._sorted_utilities():
|
|
289
|
+
comp_name = self._component_display_name(component)
|
|
290
|
+
priority = getattr(component, "priority", 0)
|
|
291
|
+
logger.debug(
|
|
292
|
+
f"Agent pre_evaluate: agent={self.name}, component={comp_name}, "
|
|
293
|
+
f"priority={priority}, artifact_count={len(current.artifacts)}"
|
|
294
|
+
)
|
|
295
|
+
try:
|
|
296
|
+
current = await component.on_pre_evaluate(self, ctx, current)
|
|
297
|
+
except Exception as exc:
|
|
298
|
+
logger.exception(
|
|
299
|
+
f"Agent pre_evaluate failed: agent={self.name}, component={comp_name}, "
|
|
300
|
+
f"priority={priority}, error={exc!s}"
|
|
301
|
+
)
|
|
302
|
+
raise
|
|
239
303
|
return current
|
|
240
304
|
|
|
241
305
|
async def _run_engines(self, ctx: Context, inputs: EvalInputs) -> EvalResult:
|
|
@@ -263,7 +327,7 @@ class Agent(metaclass=AutoTracedMeta):
|
|
|
263
327
|
result = await engine.evaluate(self, ctx, current_inputs)
|
|
264
328
|
except NotImplementedError:
|
|
265
329
|
if use_batch_mode:
|
|
266
|
-
logger.
|
|
330
|
+
logger.exception(
|
|
267
331
|
"Agent %s: engine %s does not implement evaluate_batch()",
|
|
268
332
|
self.name,
|
|
269
333
|
engine.__class__.__name__,
|
|
@@ -310,8 +374,21 @@ class Agent(metaclass=AutoTracedMeta):
|
|
|
310
374
|
self, ctx: Context, inputs: EvalInputs, result: EvalResult
|
|
311
375
|
) -> EvalResult:
|
|
312
376
|
current = result
|
|
313
|
-
for component in self.
|
|
314
|
-
|
|
377
|
+
for component in self._sorted_utilities():
|
|
378
|
+
comp_name = self._component_display_name(component)
|
|
379
|
+
priority = getattr(component, "priority", 0)
|
|
380
|
+
logger.debug(
|
|
381
|
+
f"Agent post_evaluate: agent={self.name}, component={comp_name}, "
|
|
382
|
+
f"priority={priority}, artifact_count={len(current.artifacts)}"
|
|
383
|
+
)
|
|
384
|
+
try:
|
|
385
|
+
current = await component.on_post_evaluate(self, ctx, inputs, current)
|
|
386
|
+
except Exception as exc:
|
|
387
|
+
logger.exception(
|
|
388
|
+
f"Agent post_evaluate failed: agent={self.name}, component={comp_name}, "
|
|
389
|
+
f"priority={priority}, error={exc!s}"
|
|
390
|
+
)
|
|
391
|
+
raise
|
|
315
392
|
return current
|
|
316
393
|
|
|
317
394
|
async def _make_outputs(self, ctx: Context, result: EvalResult) -> list[Artifact]:
|
|
@@ -341,9 +418,23 @@ class Agent(metaclass=AutoTracedMeta):
|
|
|
341
418
|
return produced
|
|
342
419
|
|
|
343
420
|
async def _run_post_publish(self, ctx: Context, artifacts: Sequence[Artifact]) -> None:
|
|
421
|
+
components = self._sorted_utilities()
|
|
344
422
|
for artifact in artifacts:
|
|
345
|
-
for component in
|
|
346
|
-
|
|
423
|
+
for component in components:
|
|
424
|
+
comp_name = self._component_display_name(component)
|
|
425
|
+
priority = getattr(component, "priority", 0)
|
|
426
|
+
logger.debug(
|
|
427
|
+
f"Agent post_publish: agent={self.name}, component={comp_name}, "
|
|
428
|
+
f"priority={priority}, artifact_id={artifact.id}"
|
|
429
|
+
)
|
|
430
|
+
try:
|
|
431
|
+
await component.on_post_publish(self, ctx, artifact)
|
|
432
|
+
except Exception as exc:
|
|
433
|
+
logger.exception(
|
|
434
|
+
f"Agent post_publish failed: agent={self.name}, component={comp_name}, "
|
|
435
|
+
f"priority={priority}, artifact_id={artifact.id}, error={exc!s}"
|
|
436
|
+
)
|
|
437
|
+
raise
|
|
347
438
|
|
|
348
439
|
async def _invoke_call(self, ctx: Context, artifacts: Sequence[Artifact]) -> None:
|
|
349
440
|
func = self.calls_func
|
|
@@ -359,14 +450,46 @@ class Agent(metaclass=AutoTracedMeta):
|
|
|
359
450
|
await maybe_coro
|
|
360
451
|
|
|
361
452
|
async def _run_error(self, ctx: Context, error: Exception) -> None:
|
|
362
|
-
for component in self.
|
|
363
|
-
|
|
453
|
+
for component in self._sorted_utilities():
|
|
454
|
+
comp_name = self._component_display_name(component)
|
|
455
|
+
priority = getattr(component, "priority", 0)
|
|
456
|
+
|
|
457
|
+
# Python 3.12+ TaskGroup raises BaseExceptionGroup - extract sub-exceptions
|
|
458
|
+
error_detail = str(error)
|
|
459
|
+
if isinstance(error, BaseExceptionGroup):
|
|
460
|
+
sub_exceptions = [f"{type(e).__name__}: {e}" for e in error.exceptions]
|
|
461
|
+
error_detail = f"{error!s} - Sub-exceptions: {sub_exceptions}"
|
|
462
|
+
|
|
463
|
+
logger.debug(
|
|
464
|
+
f"Agent error hook: agent={self.name}, component={comp_name}, "
|
|
465
|
+
f"priority={priority}, error={error_detail}"
|
|
466
|
+
)
|
|
467
|
+
try:
|
|
468
|
+
await component.on_error(self, ctx, error)
|
|
469
|
+
except Exception as exc:
|
|
470
|
+
logger.exception(
|
|
471
|
+
f"Agent error hook failed: agent={self.name}, component={comp_name}, "
|
|
472
|
+
f"priority={priority}, original_error={error!s}, hook_error={exc!s}"
|
|
473
|
+
)
|
|
474
|
+
raise
|
|
364
475
|
for engine in self.engines:
|
|
365
476
|
await engine.on_error(self, ctx, error)
|
|
366
477
|
|
|
367
478
|
async def _run_terminate(self, ctx: Context) -> None:
|
|
368
|
-
for component in self.
|
|
369
|
-
|
|
479
|
+
for component in self._sorted_utilities():
|
|
480
|
+
comp_name = self._component_display_name(component)
|
|
481
|
+
priority = getattr(component, "priority", 0)
|
|
482
|
+
logger.debug(
|
|
483
|
+
f"Agent terminate: agent={self.name}, component={comp_name}, priority={priority}"
|
|
484
|
+
)
|
|
485
|
+
try:
|
|
486
|
+
await component.on_terminate(self, ctx)
|
|
487
|
+
except Exception as exc:
|
|
488
|
+
logger.exception(
|
|
489
|
+
f"Agent terminate failed: agent={self.name}, component={comp_name}, "
|
|
490
|
+
f"priority={priority}, error={exc!s}"
|
|
491
|
+
)
|
|
492
|
+
raise
|
|
370
493
|
for engine in self.engines:
|
|
371
494
|
await engine.on_terminate(self, ctx)
|
|
372
495
|
|
|
@@ -396,7 +519,7 @@ class Agent(metaclass=AutoTracedMeta):
|
|
|
396
519
|
return []
|
|
397
520
|
|
|
398
521
|
default_component = OutputUtilityComponent()
|
|
399
|
-
self.
|
|
522
|
+
self._add_utilities([default_component])
|
|
400
523
|
return self.utilities
|
|
401
524
|
|
|
402
525
|
def _find_matching_artifact(
|
|
@@ -672,7 +795,8 @@ class AgentBuilder:
|
|
|
672
795
|
- AgentComponent: Base class for custom components
|
|
673
796
|
- Lifecycle hooks: on_initialize, on_pre_consume, on_post_publish, etc.
|
|
674
797
|
"""
|
|
675
|
-
|
|
798
|
+
if components:
|
|
799
|
+
self._agent._add_utilities(list(components))
|
|
676
800
|
return self
|
|
677
801
|
|
|
678
802
|
def with_engines(self, *engines: EngineComponent) -> AgentBuilder:
|
flock/components.py
CHANGED
|
@@ -56,6 +56,10 @@ class AgentComponent(BaseModel, metaclass=TracedModelMeta):
|
|
|
56
56
|
|
|
57
57
|
name: str | None = None
|
|
58
58
|
config: AgentComponentConfig = Field(default_factory=AgentComponentConfig)
|
|
59
|
+
priority: int = Field(
|
|
60
|
+
default=0,
|
|
61
|
+
description="Execution priority (lower numbers run earlier; default preserves add order).",
|
|
62
|
+
)
|
|
59
63
|
|
|
60
64
|
async def on_initialize(
|
|
61
65
|
self, agent: Agent, ctx: Context
|
flock/dashboard/collector.py
CHANGED
|
@@ -98,6 +98,8 @@ class DashboardEventCollector(AgentComponent):
|
|
|
98
98
|
Phase 3: Emits events via WebSocket using WebSocketManager.
|
|
99
99
|
"""
|
|
100
100
|
|
|
101
|
+
priority: int = -100 # Run before other agent utilities for event capture
|
|
102
|
+
|
|
101
103
|
# Use PrivateAttr for non-Pydantic fields (AgentComponent extends BaseModel)
|
|
102
104
|
_events: deque[
|
|
103
105
|
AgentActivatedEvent | MessagePublishedEvent | AgentCompletedEvent | AgentErrorEvent
|