flock-core 0.5.0b75__py3-none-any.whl → 0.5.2__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.

@@ -0,0 +1 @@
1
+ """Dashboard models for graph visualization and data structures."""
@@ -242,19 +242,51 @@ class DSPyEngine(EngineComponent):
242
242
 
243
243
  try:
244
244
  if should_stream:
245
- (
246
- raw_result,
247
- _stream_final_display_data,
248
- ) = await self._execute_streaming(
249
- dspy_mod,
250
- program,
251
- signature,
252
- description=sys_desc,
253
- payload=execution_payload,
254
- agent=agent,
255
- ctx=ctx,
256
- pre_generated_artifact_id=pre_generated_artifact_id,
245
+ # Choose streaming method based on dashboard mode
246
+ is_dashboard = orchestrator and getattr(orchestrator, "is_dashboard", False)
247
+
248
+ # DEBUG: Log routing decision
249
+ logger.info(
250
+ f"[STREAMING ROUTER] agent={agent.name}, is_dashboard={is_dashboard}, orchestrator={orchestrator is not None}"
257
251
  )
252
+
253
+ if is_dashboard:
254
+ # Dashboard mode: WebSocket-only streaming (no Rich overhead)
255
+ # This eliminates the Rich Live context that causes deadlocks with MCP tools
256
+ logger.info(
257
+ f"[STREAMING ROUTER] Routing {agent.name} to WebSocket-only method (dashboard mode)"
258
+ )
259
+ (
260
+ raw_result,
261
+ _stream_final_display_data,
262
+ ) = await self._execute_streaming_websocket_only(
263
+ dspy_mod,
264
+ program,
265
+ signature,
266
+ description=sys_desc,
267
+ payload=execution_payload,
268
+ agent=agent,
269
+ ctx=ctx,
270
+ pre_generated_artifact_id=pre_generated_artifact_id,
271
+ )
272
+ else:
273
+ # CLI mode: Rich streaming with terminal display
274
+ logger.info(
275
+ f"[STREAMING ROUTER] Routing {agent.name} to Rich streaming method (CLI mode)"
276
+ )
277
+ (
278
+ raw_result,
279
+ _stream_final_display_data,
280
+ ) = await self._execute_streaming(
281
+ dspy_mod,
282
+ program,
283
+ signature,
284
+ description=sys_desc,
285
+ payload=execution_payload,
286
+ agent=agent,
287
+ ctx=ctx,
288
+ pre_generated_artifact_id=pre_generated_artifact_id,
289
+ )
258
290
  if not self.no_output and ctx:
259
291
  ctx.state["_flock_stream_live_active"] = True
260
292
  else:
@@ -503,6 +535,221 @@ class DSPyEngine(EngineComponent):
503
535
  # Handle old format: direct payload (backwards compatible)
504
536
  return program(description=description, input=payload, context=[])
505
537
 
538
+ async def _execute_streaming_websocket_only(
539
+ self,
540
+ dspy_mod,
541
+ program,
542
+ signature,
543
+ *,
544
+ description: str,
545
+ payload: dict[str, Any],
546
+ agent: Any,
547
+ ctx: Any = None,
548
+ pre_generated_artifact_id: Any = None,
549
+ ) -> tuple[Any, None]:
550
+ """Execute streaming for WebSocket only (no Rich display).
551
+
552
+ Optimized path for dashboard mode that skips all Rich formatting overhead.
553
+ Used when multiple agents stream in parallel to avoid terminal conflicts
554
+ and deadlocks with MCP tools.
555
+
556
+ This method eliminates the Rich Live context that can cause deadlocks when
557
+ combined with MCP tool execution and parallel agent streaming.
558
+ """
559
+ logger.info(f"Agent {agent.name}: Starting WebSocket-only streaming (dashboard mode)")
560
+
561
+ # Get WebSocketManager
562
+ ws_manager = None
563
+ if ctx:
564
+ orchestrator = getattr(ctx, "orchestrator", None)
565
+ if orchestrator:
566
+ collector = getattr(orchestrator, "_dashboard_collector", None)
567
+ if collector:
568
+ ws_manager = getattr(collector, "_websocket_manager", None)
569
+
570
+ if not ws_manager:
571
+ logger.warning(
572
+ f"Agent {agent.name}: No WebSocket manager, falling back to standard execution"
573
+ )
574
+ result = await self._execute_standard(
575
+ dspy_mod, program, description=description, payload=payload
576
+ )
577
+ return result, None
578
+
579
+ # Get artifact type name for WebSocket events
580
+ artifact_type_name = "output"
581
+ if hasattr(agent, "outputs") and agent.outputs:
582
+ artifact_type_name = agent.outputs[0].spec.type_name
583
+
584
+ # Prepare stream listeners
585
+ listeners = []
586
+ try:
587
+ streaming_mod = getattr(dspy_mod, "streaming", None)
588
+ if streaming_mod and hasattr(streaming_mod, "StreamListener"):
589
+ for name, field in signature.output_fields.items():
590
+ if field.annotation is str:
591
+ listeners.append(streaming_mod.StreamListener(signature_field_name=name))
592
+ except Exception:
593
+ listeners = []
594
+
595
+ # Create streaming task
596
+ streaming_task = dspy_mod.streamify(
597
+ program,
598
+ is_async_program=True,
599
+ stream_listeners=listeners if listeners else None,
600
+ )
601
+
602
+ # Execute with appropriate payload format
603
+ if isinstance(payload, dict) and "input" in payload:
604
+ stream_generator = streaming_task(
605
+ description=description,
606
+ input=payload["input"],
607
+ context=payload.get("context", []),
608
+ )
609
+ else:
610
+ stream_generator = streaming_task(description=description, input=payload, context=[])
611
+
612
+ # Process stream (WebSocket only, no Rich display)
613
+ final_result = None
614
+ stream_sequence = 0
615
+
616
+ # Track background WebSocket broadcast tasks to prevent garbage collection
617
+ # Using fire-and-forget pattern to avoid blocking DSPy's streaming loop
618
+ ws_broadcast_tasks: set[asyncio.Task] = set()
619
+
620
+ async for value in stream_generator:
621
+ try:
622
+ from dspy.streaming import StatusMessage, StreamResponse
623
+ from litellm import ModelResponseStream
624
+ except Exception:
625
+ StatusMessage = object # type: ignore
626
+ StreamResponse = object # type: ignore
627
+ ModelResponseStream = object # type: ignore
628
+
629
+ if isinstance(value, StatusMessage):
630
+ token = getattr(value, "message", "")
631
+ if token:
632
+ try:
633
+ event = StreamingOutputEvent(
634
+ correlation_id=str(ctx.correlation_id)
635
+ if ctx and ctx.correlation_id
636
+ else "",
637
+ agent_name=agent.name,
638
+ run_id=ctx.task_id if ctx else "",
639
+ output_type="log",
640
+ content=str(token + "\n"),
641
+ sequence=stream_sequence,
642
+ is_final=False,
643
+ artifact_id=str(pre_generated_artifact_id),
644
+ artifact_type=artifact_type_name,
645
+ )
646
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
647
+ task = asyncio.create_task(ws_manager.broadcast(event))
648
+ ws_broadcast_tasks.add(task)
649
+ task.add_done_callback(ws_broadcast_tasks.discard)
650
+ stream_sequence += 1
651
+ except Exception as e:
652
+ logger.warning(f"Failed to emit streaming event: {e}")
653
+
654
+ elif isinstance(value, StreamResponse):
655
+ token = getattr(value, "chunk", None)
656
+ if token:
657
+ try:
658
+ event = StreamingOutputEvent(
659
+ correlation_id=str(ctx.correlation_id)
660
+ if ctx and ctx.correlation_id
661
+ else "",
662
+ agent_name=agent.name,
663
+ run_id=ctx.task_id if ctx else "",
664
+ output_type="llm_token",
665
+ content=str(token),
666
+ sequence=stream_sequence,
667
+ is_final=False,
668
+ artifact_id=str(pre_generated_artifact_id),
669
+ artifact_type=artifact_type_name,
670
+ )
671
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
672
+ task = asyncio.create_task(ws_manager.broadcast(event))
673
+ ws_broadcast_tasks.add(task)
674
+ task.add_done_callback(ws_broadcast_tasks.discard)
675
+ stream_sequence += 1
676
+ except Exception as e:
677
+ logger.warning(f"Failed to emit streaming event: {e}")
678
+
679
+ elif isinstance(value, ModelResponseStream):
680
+ chunk = value
681
+ token = chunk.choices[0].delta.content or ""
682
+ if token:
683
+ try:
684
+ event = StreamingOutputEvent(
685
+ correlation_id=str(ctx.correlation_id)
686
+ if ctx and ctx.correlation_id
687
+ else "",
688
+ agent_name=agent.name,
689
+ run_id=ctx.task_id if ctx else "",
690
+ output_type="llm_token",
691
+ content=str(token),
692
+ sequence=stream_sequence,
693
+ is_final=False,
694
+ artifact_id=str(pre_generated_artifact_id),
695
+ artifact_type=artifact_type_name,
696
+ )
697
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
698
+ task = asyncio.create_task(ws_manager.broadcast(event))
699
+ ws_broadcast_tasks.add(task)
700
+ task.add_done_callback(ws_broadcast_tasks.discard)
701
+ stream_sequence += 1
702
+ except Exception as e:
703
+ logger.warning(f"Failed to emit streaming event: {e}")
704
+
705
+ elif isinstance(value, dspy_mod.Prediction):
706
+ final_result = value
707
+ # Send final events
708
+ try:
709
+ event = StreamingOutputEvent(
710
+ correlation_id=str(ctx.correlation_id)
711
+ if ctx and ctx.correlation_id
712
+ else "",
713
+ agent_name=agent.name,
714
+ run_id=ctx.task_id if ctx else "",
715
+ output_type="log",
716
+ content=f"\nAmount of output tokens: {stream_sequence}",
717
+ sequence=stream_sequence,
718
+ is_final=True,
719
+ artifact_id=str(pre_generated_artifact_id),
720
+ artifact_type=artifact_type_name,
721
+ )
722
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
723
+ task = asyncio.create_task(ws_manager.broadcast(event))
724
+ ws_broadcast_tasks.add(task)
725
+ task.add_done_callback(ws_broadcast_tasks.discard)
726
+
727
+ event = StreamingOutputEvent(
728
+ correlation_id=str(ctx.correlation_id)
729
+ if ctx and ctx.correlation_id
730
+ else "",
731
+ agent_name=agent.name,
732
+ run_id=ctx.task_id if ctx else "",
733
+ output_type="log",
734
+ content="--- End of output ---",
735
+ sequence=stream_sequence + 1,
736
+ is_final=True,
737
+ artifact_id=str(pre_generated_artifact_id),
738
+ artifact_type=artifact_type_name,
739
+ )
740
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
741
+ task = asyncio.create_task(ws_manager.broadcast(event))
742
+ ws_broadcast_tasks.add(task)
743
+ task.add_done_callback(ws_broadcast_tasks.discard)
744
+ except Exception as e:
745
+ logger.warning(f"Failed to emit final streaming event: {e}")
746
+
747
+ if final_result is None:
748
+ raise RuntimeError(f"Agent {agent.name}: Streaming did not yield a final prediction")
749
+
750
+ logger.info(f"Agent {agent.name}: WebSocket streaming completed ({stream_sequence} tokens)")
751
+ return final_result, None
752
+
506
753
  async def _execute_streaming(
507
754
  self,
508
755
  dspy_mod,
@@ -930,3 +1177,11 @@ __all__ = ["DSPyEngine"]
930
1177
 
931
1178
  # Apply the Rich Live patch when this module is imported
932
1179
  _apply_live_patch_on_import()
1180
+
1181
+ # Apply the DSPy streaming patch to fix deadlocks with MCP tools
1182
+ try:
1183
+ from flock.patches.dspy_streaming_patch import apply_patch as apply_dspy_streaming_patch
1184
+
1185
+ apply_dspy_streaming_patch()
1186
+ except Exception:
1187
+ pass # Silently ignore if patch fails to apply
flock/orchestrator.py CHANGED
@@ -668,8 +668,10 @@ class Flock(metaclass=AutoTracedMeta):
668
668
  >>> # Publish with tags for channel routing
669
669
  >>> await orchestrator.publish(task, tags={"urgent", "backend"})
670
670
  """
671
- init_console(clear_screen=True, show_banner=True, model=self.model)
672
671
  self.is_dashboard = is_dashboard
672
+ # Only show banner in CLI mode, not dashboard mode
673
+ if not self.is_dashboard:
674
+ init_console(clear_screen=True, show_banner=True, model=self.model)
673
675
  # Handle different input types
674
676
  if isinstance(obj, Artifact):
675
677
  # Already an artifact - publish as-is
@@ -0,0 +1,5 @@
1
+ """Monkey-patches for third-party libraries to fix known issues."""
2
+
3
+ from flock.patches.dspy_streaming_patch import apply_patch, restore_original
4
+
5
+ __all__ = ["apply_patch", "restore_original"]
@@ -0,0 +1,82 @@
1
+ """
2
+ Monkey-patch for DSPy's sync_send_to_stream function.
3
+
4
+ The original DSPy implementation blocks the event loop with future.result(),
5
+ causing deadlocks when using MCP tools with dashboard streaming.
6
+
7
+ This patch replaces it with a non-blocking fire-and-forget approach.
8
+ """
9
+
10
+ import asyncio
11
+ import logging
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ def patched_sync_send_to_stream(stream, message):
17
+ """Non-blocking replacement for DSPy's sync_send_to_stream.
18
+
19
+ Instead of blocking with future.result(), this version:
20
+ 1. Schedules the send as a background task (fire-and-forget)
21
+ 2. Never blocks the calling thread
22
+ 3. Logs errors but doesn't raise them
23
+
24
+ This allows MCP tool callbacks to complete without deadlocking.
25
+ """
26
+
27
+ async def _send():
28
+ try:
29
+ await stream.send(message)
30
+ except Exception as e:
31
+ logger.debug(f"DSPy status message send failed (non-critical): {e}")
32
+
33
+ try:
34
+ # Try to get the running event loop
35
+ loop = asyncio.get_running_loop()
36
+
37
+ # Schedule as a background task (fire-and-forget)
38
+ # This won't block - the task runs independently
39
+ loop.create_task(_send())
40
+
41
+ except RuntimeError:
42
+ # No event loop running - this is a sync context
43
+ # We can safely create a new loop and run the task
44
+ try:
45
+ asyncio.run(_send())
46
+ except Exception as e:
47
+ logger.debug(f"DSPy status message send failed in sync context (non-critical): {e}")
48
+
49
+
50
+ def apply_patch():
51
+ """Apply the monkey-patch to DSPy's streaming module."""
52
+ try:
53
+ import dspy.streaming.messages as dspy_messages
54
+
55
+ # Store original for reference (in case we need to restore)
56
+ if not hasattr(dspy_messages, "_original_sync_send_to_stream"):
57
+ dspy_messages._original_sync_send_to_stream = dspy_messages.sync_send_to_stream
58
+
59
+ # Replace with our non-blocking version
60
+ dspy_messages.sync_send_to_stream = patched_sync_send_to_stream
61
+
62
+ logger.info("Applied DSPy streaming patch - status messages are now non-blocking")
63
+ return True
64
+
65
+ except Exception as e:
66
+ logger.warning(f"Failed to apply DSPy streaming patch: {e}")
67
+ return False
68
+
69
+
70
+ def restore_original():
71
+ """Restore the original DSPy function (for testing/debugging)."""
72
+ try:
73
+ import dspy.streaming.messages as dspy_messages
74
+
75
+ if hasattr(dspy_messages, "_original_sync_send_to_stream"):
76
+ dspy_messages.sync_send_to_stream = dspy_messages._original_sync_send_to_stream
77
+ logger.info("Restored original DSPy streaming function")
78
+ return True
79
+
80
+ except Exception as e:
81
+ logger.warning(f"Failed to restore original DSPy function: {e}")
82
+ return False
@@ -1,13 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.5.0b75
4
- Summary: Add your description here
3
+ Version: 0.5.2
4
+ Summary: Flock: A declrative framework for building and orchestrating AI agents.
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
+ License: MIT
6
7
  License-File: LICENSE
7
8
  Requires-Python: >=3.10
8
9
  Requires-Dist: aiosqlite>=0.20.0
9
10
  Requires-Dist: devtools>=0.12.2
10
- Requires-Dist: dspy==3.0.0
11
+ Requires-Dist: dspy==3.0.4b1
11
12
  Requires-Dist: duckdb>=1.1.0
12
13
  Requires-Dist: fastapi>=0.117.1
13
14
  Requires-Dist: hanging-threads>=2.0.7
@@ -31,13 +32,13 @@ Requires-Dist: websockets>=15.0.1
31
32
  Description-Content-Type: text/markdown
32
33
 
33
34
  <p align="center">
34
- <img alt="Flock Banner" src="https://raw.githubusercontent.com/whiteducksoftware/flock/master/docs/assets/images/flock.png" width="800">
35
+ <img alt="Flock Banner" src="docs/assets/images/flock.png" width="800">
35
36
  </p>
36
37
  <p align="center">
37
- <a href="https://docs.flock.whiteduck.de" target="_blank"><img alt="Documentation" src="https://img.shields.io/badge/docs-online-blue?style=for-the-badge&logo=readthedocs"></a>
38
+ <a href="https://whiteducksoftware.github.io/flock/" target="_blank"><img alt="Documentation" src="https://img.shields.io/badge/docs-online-blue?style=for-the-badge&logo=readthedocs"></a>
38
39
  <a href="https://pypi.org/project/flock-core/" target="_blank"><img alt="PyPI Version" src="https://img.shields.io/pypi/v/flock-core?style=for-the-badge&logo=pypi&label=pip%20version"></a>
39
40
  <img alt="Python Version" src="https://img.shields.io/badge/python-3.10%2B-blue?style=for-the-badge&logo=python">
40
- <a href="LICENSE" target="_blank"><img alt="License" src="https://img.shields.io/pypi/l/flock-core?style=for-the-badge"></a>
41
+ <a href="LICENSE" target="_blank"><img alt="License" src="https://img.shields.io/github/license/whiteducksoftware/flock?style=for-the-badge"></a>
41
42
  <a href="https://whiteduck.de" target="_blank"><img alt="Built by white duck" src="https://img.shields.io/badge/Built%20by-white%20duck%20GmbH-white?style=for-the-badge&labelColor=black"></a>
42
43
  <img alt="Test Coverage" src="https://img.shields.io/badge/coverage-77%25-green?style=for-the-badge">
43
44
  <img alt="Tests" src="https://img.shields.io/badge/tests-743%20passing-brightgreen?style=for-the-badge">
@@ -51,14 +52,14 @@ Description-Content-Type: text/markdown
51
52
 
52
53
  Flock is a production-focused framework for orchestrating AI agents through **declarative type contracts** and **blackboard architecture**—proven patterns from distributed systems, decades of experience with microservice architectures, and classical AI—now applied to modern LLMs.
53
54
 
54
- **📖 [Read the full documentation →](https://docs.flock.whiteduck.de)**
55
+ **📖 [Read the full documentation →](https://whiteducksoftware.github.io/flock)**
55
56
 
56
57
  **Quick links:**
57
- - **[Getting Started](https://docs.flock.whiteduck.de/getting-started/installation/)** - Installation and first steps
58
- - **[Tutorials](https://docs.flock.whiteduck.de/tutorials/)** - Step-by-step learning path
59
- - **[User Guides](https://docs.flock.whiteduck.de/guides/)** - In-depth feature documentation
60
- - **[API Reference](https://docs.flock.whiteduck.de/reference/api/)** - Complete API documentation
61
- - **[Roadmap](https://docs.flock.whiteduck.de/about/roadmap/)** - What's coming in v1.0
58
+ - **[Getting Started](https://whiteducksoftware.github.io/flock/getting-started/installation/)** - Installation and first steps
59
+ - **[Tutorials](https://whiteducksoftware.github.io/flock/tutorials/)** - Step-by-step learning path
60
+ - **[User Guides](https://whiteducksoftware.github.io/flock/guides/)** - In-depth feature documentation
61
+ - **[API Reference](https://whiteducksoftware.github.io/flock/reference/api/)** - Complete API documentation
62
+ - **[Roadmap](https://whiteducksoftware.github.io/flock/about/roadmap/)** - What's coming in v1.0
62
63
 
63
64
  ---
64
65
 
@@ -675,13 +676,15 @@ Flock uses a fundamentally different coordination pattern than most multi-agent
675
676
  - Type-safe retrieval API (`get_by_type()`)
676
677
 
677
678
  **⚠️ What's missing for large-scale production:**
678
- - **Persistent blackboard** - Currently in-memory only
679
- - **Advanced retry logic** - Basic only
679
+ - **Advanced retry logic** - Basic only (exponential backoff planned)
680
680
  - **Event replay** - No Kafka integration yet
681
681
  - **Kubernetes-native deployment** - No Helm chart yet
682
682
  - **OAuth/RBAC** - Dashboard has no auth
683
683
 
684
- All planned for v1.0
684
+ **✅ Available today:**
685
+ - **Persistent blackboard** - SQLiteBlackboardStore (see above)
686
+
687
+ All missing features planned for v1.0
685
688
 
686
689
  ### Recommended Use Cases Today
687
690
 
@@ -873,24 +876,29 @@ pip install flock-core
873
876
  # Set API key
874
877
  export OPENAI_API_KEY="sk-..."
875
878
 
876
- # Try the workshop
879
+ # Try the examples
877
880
  git clone https://github.com/whiteducksoftware/flock-flow.git
878
881
  cd flock-flow
879
- uv run python examples/05-claudes-workshop/lesson_01_code_detective.py
882
+
883
+ # CLI examples with detailed output
884
+ uv run python examples/01-cli/01_declarative_pizza.py
885
+
886
+ # Dashboard examples with visualization
887
+ uv run python examples/02-dashboard/01_declarative_pizza.py
880
888
  ```
881
889
 
882
890
  **Learn by doing:**
883
- - 📚 [7-Lesson Workshop](examples/05-claudes-workshop/) - Progressive lessons from basics to advanced
884
- - 🆚 [The Blackboard](examples/02-the-blackboard/) - See data-driven orchestration without graphs
885
- - 🎯 [Declarative Basics](examples/01-the-declarative-way/) - Understanding declarative programming
886
- - 📖 [Documentation](https://docs.flock.whiteduck.de) - Complete online documentation
891
+ - 📚 [Examples README](examples/README.md) - 12-step learning path from basics to advanced
892
+ - 🖥️ [CLI Examples](examples/01-cli/) - Detailed console output examples (01-12)
893
+ - 📊 [Dashboard Examples](examples/02-dashboard/) - Interactive visualization examples (01-12)
894
+ - 📖 [Documentation](https://whiteducksoftware.github.io/flock) - Complete online documentation
887
895
  - 📘 [AGENTS.md](AGENTS.md) - Development guide
888
896
 
889
897
  ---
890
898
 
891
899
  ## Contributing
892
900
 
893
- We're building Flock in the open. See **[Contributing Guide](https://docs.flock.whiteduck.de/about/contributing/)** for development setup, or check [CONTRIBUTING.md](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md) locally.
901
+ We're building Flock in the open. See **[Contributing Guide](https://whiteducksoftware.github.io/flock/about/contributing/)** for development setup, or check [CONTRIBUTING.md](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md) locally.
894
902
 
895
903
  **We welcome:**
896
904
  - Bug reports and feature requests
@@ -953,12 +961,12 @@ We're calling this 0.5 to signal:
953
961
 
954
962
  **"Declarative contracts eliminate prompt hell. Blackboard architecture eliminates graph spaghetti. Proven patterns applied to modern LLMs."**
955
963
 
956
- [⭐ Star on GitHub](https://github.com/whiteducksoftware/flock-flow) | [📖 Documentation](https://docs.flock.whiteduck.de) | [🚀 Try Examples](examples/) | [💼 Enterprise Support](mailto:support@whiteduck.de)
964
+ [⭐ Star on GitHub](https://github.com/whiteducksoftware/flock-flow) | [📖 Documentation](https://whiteducksoftware.github.io/flock) | [🚀 Try Examples](examples/) | [💼 Enterprise Support](mailto:support@whiteduck.de)
957
965
 
958
966
  </div>
959
967
 
960
968
  ---
961
969
 
962
- **Last Updated:** October 8, 2025
970
+ **Last Updated:** October 13, 2025
963
971
  **Version:** Flock 0.5.0 (Blackboard Edition)
964
972
  **Status:** Production-Ready Core, Enterprise Features Roadmapped
@@ -4,7 +4,7 @@ flock/artifacts.py,sha256=3vQQ1J7QxTzeQBUGaNLiyojlmBv1NfdhFC98-qj8fpU,2541
4
4
  flock/cli.py,sha256=lPtKxEXnGtyuTh0gyG3ixEIFS4Ty6Y0xsPd6SpUTD3U,4526
5
5
  flock/components.py,sha256=17vhNMHKc3VUruEbSdb9YNKcDziIe0coS9jpfWBmX4o,6259
6
6
  flock/examples.py,sha256=eQb8k6EYBbUhauFuSN_0EIIu5KW0mTqJU0HM4-p14sc,3632
7
- flock/orchestrator.py,sha256=g_gxZbOcFsuBk0aw6F41Mbsrc0nF2BBjah6vxvm7rR4,36564
7
+ flock/orchestrator.py,sha256=f7FD1i2bcpkHEER0w3DEgzcWp1AmmBSbegVODdhYxdY,36661
8
8
  flock/registry.py,sha256=s0-H-TMtOsDZiZQCc7T1tYiWQg3OZHn5T--jaI_INIc,4786
9
9
  flock/runtime.py,sha256=UG-38u578h628mSddBmyZn2VIzFQ0wlHCpCALFiScqA,8518
10
10
  flock/service.py,sha256=JDdjjPTPH6NFezAr8x6svtqxIGXA7-AyHS11GF57g9Q,11041
@@ -20,12 +20,13 @@ flock/dashboard/graph_builder.py,sha256=u5Hp007Wr_v3aQI_0YzTit9hAGDc-gUiilnj-p11
20
20
  flock/dashboard/launcher.py,sha256=dCfwaeMLtyIkik3aVSEsbBdABS5ADRlKWYkih7sF5hM,8196
21
21
  flock/dashboard/service.py,sha256=PzyJS3T3lSoC1sULdfKqUJyu2UUhtSV5xEG0LPhO4qI,39071
22
22
  flock/dashboard/websocket.py,sha256=_DCZApJPXc8OQnxFDFS9TA9ozq7kM73QByRj-_a8n-8,9508
23
+ flock/dashboard/models/__init__.py,sha256=T4Yz8IXMm7lBqa2HLDSv7WJBtaKcdZIlTrz6GHNFZxs,68
23
24
  flock/dashboard/models/graph.py,sha256=t159CMNavFYZB-qvSE5HRh9Zi_HOR4RYc8VzIngpx_E,5316
24
25
  flock/dashboard/static_v2/index.html,sha256=iWL-fgTY2egom20DMvSOpuYZ6pC5AVvdNZcj-EvPm5w,422
25
26
  flock/dashboard/static_v2/assets/index-DFRnI_mt.js,sha256=PVrBXxY3Igbf9dqtsWoCbhogEhibapLAwlMYV5Gv4pY,764870
26
27
  flock/dashboard/static_v2/assets/index-fPLNdmp1.css,sha256=skpvfkkrlw7WbmBh7HN-rUKAtKP-gpuLUH4klUgFHT4,74529
27
28
  flock/engines/__init__.py,sha256=waNyObJ8PKCLFZL3WUFynxSK-V47m559P3Px-vl_OSc,124
28
- flock/engines/dspy_engine.py,sha256=COb9RBVeT-5uESBhpRV4vShNE70c0gizd5ej-9PEQQ0,38989
29
+ flock/engines/dspy_engine.py,sha256=o_k9mnWuxGN2jEL8KQmaBCGi6Aw8hQb9AZPsQRLRw3U,50921
29
30
  flock/frontend/README.md,sha256=R1gqm524Xa5PZAkfl-IJDEf6VsBJ6ThrpY7SyDawjog,26232
30
31
  flock/frontend/index.html,sha256=BFg1VR_YVAJ_MGN16xa7sT6wTGwtFYUhfJhGuKv89VM,312
31
32
  flock/frontend/package-lock.json,sha256=1edo2JDle0if_MljnK4Xto7Q7hhGUEBQAvQFqKy9RzQ,150798
@@ -181,6 +182,8 @@ flock/mcp/types/handlers.py,sha256=6ukkSMv1VZSfk2QDUiJnm8xifHnQvWZsxWXqN21BYSg,7
181
182
  flock/mcp/types/types.py,sha256=ZbzbVihABFnfmZz2X-CCN7hQDzaSY0T-en43PFbFwQQ,11469
182
183
  flock/mcp/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
184
  flock/mcp/util/helpers.py,sha256=jO8DqqSb_S4dyvsxv5vlMGRoMx92Su_5-Uv17gQNuLU,740
185
+ flock/patches/__init__.py,sha256=2turkIzq6C_DpIKDwah7aPd-1RFOAGX7dxTkaBd9X4w,193
186
+ flock/patches/dspy_streaming_patch.py,sha256=1vJ7t_PlBBza6MAQPiBhFn2A0k42tdYGs-WpC77BmDA,2762
184
187
  flock/themes/3024-day.toml,sha256=uOVHqEzSyHx0WlUk3D0lne4RBsNBAPCTy3C58yU7kEY,667
185
188
  flock/themes/3024-night.toml,sha256=qsXUwd6ZYz6J-R129_Ao2TKlvvK60svhZJJjB5c8Tfo,1667
186
189
  flock/themes/aardvark-blue.toml,sha256=5ZgsxP3pWLPN3yJ2Wd9ErCo7fy_VJpIfje4kriDKlqo,1667
@@ -518,8 +521,8 @@ flock/themes/zenburned.toml,sha256=UEmquBbcAO3Zj652XKUwCsNoC2iQSlIh-q5c6DH-7Kc,1
518
521
  flock/themes/zenwritten-dark.toml,sha256=-dgaUfg1iCr5Dv4UEeHv_cN4GrPUCWAiHSxWK20X1kI,1663
519
522
  flock/themes/zenwritten-light.toml,sha256=G1iEheCPfBNsMTGaVpEVpDzYBHA_T-MV27rolUYolmE,1666
520
523
  flock/utility/output_utility_component.py,sha256=yVHhlIIIoYKziI5UyT_zvQb4G-NsxCTgLwA1wXXTTj4,9047
521
- flock_core-0.5.0b75.dist-info/METADATA,sha256=lmtrMzJUBxGVur4A4QicG3qw3RzJcUGif0r6pHSzcY4,36377
522
- flock_core-0.5.0b75.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
523
- flock_core-0.5.0b75.dist-info/entry_points.txt,sha256=UQdPmtHd97gSA_IdLt9MOd-1rrf_WO-qsQeIiHWVrp4,42
524
- flock_core-0.5.0b75.dist-info/licenses/LICENSE,sha256=U3IZuTbC0yLj7huwJdldLBipSOHF4cPf6cUOodFiaBE,1072
525
- flock_core-0.5.0b75.dist-info/RECORD,,
524
+ flock_core-0.5.2.dist-info/METADATA,sha256=tCrSJS6TpMQftwK0xDIAmW3cK2-2r33WaM58tyvX4i0,36666
525
+ flock_core-0.5.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
526
+ flock_core-0.5.2.dist-info/entry_points.txt,sha256=UQdPmtHd97gSA_IdLt9MOd-1rrf_WO-qsQeIiHWVrp4,42
527
+ flock_core-0.5.2.dist-info/licenses/LICENSE,sha256=U3IZuTbC0yLj7huwJdldLBipSOHF4cPf6cUOodFiaBE,1072
528
+ flock_core-0.5.2.dist-info/RECORD,,