flock-core 0.5.11__tar.gz → 0.5.21__tar.gz
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_core-0.5.21/AGENTS.md +1789 -0
- flock_core-0.5.21/CONTRIBUTING.md +721 -0
- flock_core-0.5.21/PKG-INFO +1327 -0
- flock_core-0.5.21/README.md +1294 -0
- flock_core-0.5.21/ROADMAP.md +165 -0
- flock_core-0.5.21/USECASES.md +561 -0
- flock_core-0.5.21/docs/about/changelog.md +1088 -0
- flock_core-0.5.21/docs/architecture.md +1016 -0
- flock_core-0.5.21/docs/getting-started/quick-start.md +596 -0
- flock_core-0.5.21/docs/guides/batch-processing.md +816 -0
- flock_core-0.5.21/docs/guides/blackboard.md +795 -0
- flock_core-0.5.21/docs/guides/context-providers.md +1515 -0
- flock_core-0.5.21/docs/guides/fan-out.md +1092 -0
- flock_core-0.5.21/docs/guides/join-operations.md +786 -0
- flock_core-0.5.21/docs/guides/mcp-roots.md +416 -0
- flock_core-0.5.21/docs/guides/patterns.md +1232 -0
- flock_core-0.5.21/docs/guides/testing.md +709 -0
- flock_core-0.5.21/docs/guides/tracing/unified-tracing.md +374 -0
- flock_core-0.5.21/docs/guides/use-cases.md +561 -0
- flock_core-0.5.21/docs/guides/visibility.md +890 -0
- flock_core-0.5.21/docs/patterns/async_patterns.md +802 -0
- flock_core-0.5.21/docs/patterns/error_handling.md +521 -0
- flock_core-0.5.21/docs/reference/index.md +335 -0
- flock_core-0.5.21/docs/tutorials/advanced-patterns.md +437 -0
- flock_core-0.5.21/docs/tutorials/conditional-routing.md +334 -0
- flock_core-0.5.21/docs/tutorials/connect_with_ollama.md +255 -0
- flock_core-0.5.21/docs/tutorials/multi-agent-workflow.md +383 -0
- flock_core-0.5.21/docs/tutorials/your-first-agent.md +229 -0
- flock_core-0.5.21/examples/00-patterns/publish/01-single_publish.py +44 -0
- flock_core-0.5.21/examples/00-patterns/publish/02-multi_publish.py +59 -0
- flock_core-0.5.21/examples/00-patterns/publish/03-multi-artifact-multi-publish.py +59 -0
- flock_core-0.5.21/examples/00-patterns/publish/04-fan-out.py +37 -0
- flock_core-0.5.21/examples/00-patterns/publish/05-multi-fan-out.py +76 -0
- flock_core-0.5.21/examples/00-patterns/visibility/01_basic_visibility.py +144 -0
- flock_core-0.5.21/examples/01-getting-started/01_declarative_pizza.py +65 -0
- flock_core-0.5.21/examples/01-getting-started/02_input_and_output.py +82 -0
- flock_core-0.5.21/examples/01-getting-started/03_code_detective.py +109 -0
- flock_core-0.5.21/examples/01-getting-started/04_movie_generation.py +109 -0
- flock_core-0.5.21/examples/01-getting-started/05_mcp_and_tools.py +144 -0
- flock_core-0.5.21/examples/01-getting-started/06_mcp_roots.py +143 -0
- flock_core-0.5.21/examples/01-getting-started/07_web_detective.py +147 -0
- flock_core-0.5.21/examples/01-getting-started/08_band_formation.py +118 -0
- flock_core-0.5.21/examples/01-getting-started/09_debate_club.py +134 -0
- flock_core-0.5.21/examples/01-getting-started/10_news_agency.py +126 -0
- flock_core-0.5.21/examples/01-getting-started/11_tracing_detective.py +116 -0
- flock_core-0.5.21/examples/01-getting-started/12_secret_agents.py +126 -0
- flock_core-0.5.21/examples/01-getting-started/13_medical_diagnostics_joinspec.py +174 -0
- flock_core-0.5.21/examples/01-getting-started/14_ecommerce_batch_processing.py +166 -0
- flock_core-0.5.21/examples/01-getting-started/15_iot_sensor_batching.py +209 -0
- flock_core-0.5.21/examples/01-getting-started/16_news_batching.py +154 -0
- flock_core-0.5.21/examples/01-getting-started/README.md +167 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_01_code_detective.py +71 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_02_band_formation.py +99 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_03_web_detective.py +108 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_04_debate_club.py +103 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_05_tracing_detective.py +121 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_06_secret_agents.py +117 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_07_news_agency.py +142 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_08_the_matchmaker.py +220 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_09_the_batch_optimizer.py +226 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_10_the_smart_factory.py +307 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_11_performance_monitor.py +355 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_12_confidence_booster.py +341 -0
- flock_core-0.5.21/examples/03-claudes-workshop/lesson_13_regex_matcher.py +296 -0
- flock_core-0.5.21/examples/04-misc/01_persistent_pizza.py +122 -0
- flock_core-0.5.21/examples/04-misc/02-dashboard-edge-cases.py +95 -0
- flock_core-0.5.21/examples/04-misc/03-scale-test-100-agents.py +130 -0
- flock_core-0.5.21/examples/04-misc/04_persistent_pizza_dashboard.py +106 -0
- flock_core-0.5.21/examples/04-misc/05_lm_studio.py +35 -0
- flock_core-0.5.21/examples/04-misc/06_prd.py +525 -0
- flock_core-0.5.21/examples/05-engines/emoji_mood_engine.py +131 -0
- flock_core-0.5.21/examples/05-engines/potion_batch_engine.py +146 -0
- flock_core-0.5.21/examples/06-agent-components/cheer_meter_component.py +116 -0
- flock_core-0.5.21/examples/06-agent-components/plot_twist_component.py +136 -0
- flock_core-0.5.21/examples/07-orchestrator-components/kitchen_monitor_component.py +211 -0
- flock_core-0.5.21/examples/07-orchestrator-components/quest_tracker_component.py +163 -0
- flock_core-0.5.21/pyproject.toml +188 -0
- flock_core-0.5.21/scripts/phase8_file_moves.sh +54 -0
- flock_core-0.5.21/scripts/update_imports.py +108 -0
- flock_core-0.5.21/src/flock/__init__.py +16 -0
- flock_core-0.5.21/src/flock/agent/__init__.py +30 -0
- flock_core-0.5.21/src/flock/agent/builder_helpers.py +192 -0
- flock_core-0.5.21/src/flock/agent/builder_validator.py +169 -0
- flock_core-0.5.21/src/flock/agent/component_lifecycle.py +325 -0
- flock_core-0.5.21/src/flock/agent/context_resolver.py +141 -0
- flock_core-0.5.21/src/flock/agent/mcp_integration.py +212 -0
- flock_core-0.5.21/src/flock/agent/output_processor.py +304 -0
- flock_core-0.5.21/src/flock/api/__init__.py +20 -0
- flock_core-0.5.21/src/flock/api/models.py +283 -0
- flock_core-0.5.21/src/flock/api/service.py +348 -0
- flock_core-0.5.21/src/flock/cli.py +149 -0
- flock_core-0.5.21/src/flock/components/__init__.py +41 -0
- flock_core-0.5.21/src/flock/components/agent/__init__.py +22 -0
- flock_core-0.5.21/src/flock/components/agent/base.py +223 -0
- flock_core-0.5.21/src/flock/components/agent/output_utility.py +251 -0
- flock_core-0.5.21/src/flock/components/orchestrator/__init__.py +22 -0
- flock_core-0.5.21/src/flock/components/orchestrator/base.py +408 -0
- flock_core-0.5.21/src/flock/components/orchestrator/circuit_breaker.py +95 -0
- flock_core-0.5.21/src/flock/components/orchestrator/collection.py +143 -0
- flock_core-0.5.21/src/flock/components/orchestrator/deduplication.py +78 -0
- flock_core-0.5.21/src/flock/core/__init__.py +30 -0
- flock_core-0.5.21/src/flock/core/agent.py +953 -0
- flock_core-0.5.21/src/flock/core/artifacts.py +86 -0
- flock_core-0.5.21/src/flock/core/context_provider.py +531 -0
- flock_core-0.5.21/src/flock/core/orchestrator.py +1102 -0
- flock_core-0.5.21/src/flock/core/store.py +878 -0
- flock_core-0.5.21/src/flock/core/subscription.py +176 -0
- flock_core-0.5.21/src/flock/dashboard/collector.py +584 -0
- flock_core-0.5.21/src/flock/dashboard/events.py +268 -0
- flock_core-0.5.21/src/flock/dashboard/graph_builder.py +835 -0
- flock_core-0.5.21/src/flock/dashboard/routes/__init__.py +21 -0
- flock_core-0.5.21/src/flock/dashboard/routes/control.py +327 -0
- flock_core-0.5.21/src/flock/dashboard/routes/helpers.py +340 -0
- flock_core-0.5.21/src/flock/dashboard/routes/themes.py +76 -0
- flock_core-0.5.21/src/flock/dashboard/routes/traces.py +521 -0
- flock_core-0.5.21/src/flock/dashboard/routes/websocket.py +108 -0
- flock_core-0.5.21/src/flock/dashboard/service.py +161 -0
- flock_core-0.5.21/src/flock/engines/dspy/__init__.py +20 -0
- flock_core-0.5.21/src/flock/engines/dspy/artifact_materializer.py +216 -0
- flock_core-0.5.21/src/flock/engines/dspy/signature_builder.py +474 -0
- flock_core-0.5.21/src/flock/engines/dspy/streaming_executor.py +812 -0
- flock_core-0.5.21/src/flock/engines/dspy_engine.py +512 -0
- flock_core-0.5.21/src/flock/engines/examples/simple_batch_engine.py +83 -0
- flock_core-0.5.21/src/flock/engines/streaming/__init__.py +3 -0
- flock_core-0.5.21/src/flock/engines/streaming/sinks.py +489 -0
- flock_core-0.5.21/src/flock/examples.py +135 -0
- flock_core-0.5.21/src/flock/logging/logging.py +576 -0
- flock_core-0.5.21/src/flock/models/__init__.py +10 -0
- flock_core-0.5.21/src/flock/orchestrator/__init__.py +45 -0
- flock_core-0.5.21/src/flock/orchestrator/artifact_collector.py +161 -0
- flock_core-0.5.21/src/flock/orchestrator/artifact_manager.py +168 -0
- flock_core-0.5.21/src/flock/orchestrator/batch_accumulator.py +254 -0
- flock_core-0.5.21/src/flock/orchestrator/component_runner.py +389 -0
- flock_core-0.5.21/src/flock/orchestrator/context_builder.py +167 -0
- flock_core-0.5.21/src/flock/orchestrator/correlation_engine.py +224 -0
- flock_core-0.5.21/src/flock/orchestrator/event_emitter.py +167 -0
- flock_core-0.5.21/src/flock/orchestrator/initialization.py +184 -0
- flock_core-0.5.21/src/flock/orchestrator/lifecycle_manager.py +226 -0
- flock_core-0.5.21/src/flock/orchestrator/mcp_manager.py +202 -0
- flock_core-0.5.21/src/flock/orchestrator/scheduler.py +189 -0
- flock_core-0.5.21/src/flock/orchestrator/server_manager.py +234 -0
- flock_core-0.5.21/src/flock/orchestrator/tracing.py +147 -0
- flock_core-0.5.21/src/flock/storage/__init__.py +10 -0
- flock_core-0.5.21/src/flock/storage/artifact_aggregator.py +158 -0
- flock_core-0.5.21/src/flock/storage/in_memory/__init__.py +6 -0
- flock_core-0.5.21/src/flock/storage/in_memory/artifact_filter.py +114 -0
- flock_core-0.5.21/src/flock/storage/in_memory/history_aggregator.py +115 -0
- flock_core-0.5.21/src/flock/storage/sqlite/__init__.py +10 -0
- flock_core-0.5.21/src/flock/storage/sqlite/agent_history_queries.py +154 -0
- flock_core-0.5.21/src/flock/storage/sqlite/consumption_loader.py +100 -0
- flock_core-0.5.21/src/flock/storage/sqlite/query_builder.py +112 -0
- flock_core-0.5.21/src/flock/storage/sqlite/query_params_builder.py +91 -0
- flock_core-0.5.21/src/flock/storage/sqlite/schema_manager.py +168 -0
- flock_core-0.5.21/src/flock/storage/sqlite/summary_queries.py +194 -0
- flock_core-0.5.21/src/flock/utils/__init__.py +14 -0
- flock_core-0.5.21/src/flock/utils/async_utils.py +67 -0
- flock_core-0.5.21/src/flock/utils/runtime.py +316 -0
- flock_core-0.5.21/src/flock/utils/time_utils.py +53 -0
- flock_core-0.5.21/src/flock/utils/type_resolution.py +38 -0
- flock_core-0.5.21/src/flock/utils/utilities.py +329 -0
- flock_core-0.5.21/src/flock/utils/validation.py +57 -0
- flock_core-0.5.21/src/flock/utils/visibility.py +79 -0
- flock_core-0.5.21/src/flock/utils/visibility_utils.py +134 -0
- flock_core-0.5.21/tests/agent/test_component_lifecycle.py +375 -0
- flock_core-0.5.21/tests/agent/test_context_resolver.py +170 -0
- flock_core-0.5.21/tests/agent/test_mcp_integration.py +297 -0
- flock_core-0.5.21/tests/agent/test_output_processor.py +332 -0
- flock_core-0.5.21/tests/conftest.py +145 -0
- flock_core-0.5.21/tests/contract/test_agent_payload_selection_contract.py +173 -0
- flock_core-0.5.21/tests/contract/test_artifact_storage_contract.py +139 -0
- flock_core-0.5.21/tests/dashboard/test_logic_operations_api.py +1124 -0
- flock_core-0.5.21/tests/dashboard/test_logic_operations_events.py +626 -0
- flock_core-0.5.21/tests/e2e/test_critical_scenarios.py +691 -0
- flock_core-0.5.21/tests/integration/test_collector_orchestrator.py +373 -0
- flock_core-0.5.21/tests/integration/test_orchestrator_dashboard.py +615 -0
- flock_core-0.5.21/tests/integration/test_sqlite_store_integration.py +37 -0
- flock_core-0.5.21/tests/integration/test_websocket_protocol.py +502 -0
- flock_core-0.5.21/tests/storage/__init__.py +1 -0
- flock_core-0.5.21/tests/storage/in_memory/__init__.py +1 -0
- flock_core-0.5.21/tests/storage/in_memory/test_artifact_filter.py +191 -0
- flock_core-0.5.21/tests/storage/in_memory/test_history_aggregator.py +217 -0
- flock_core-0.5.21/tests/storage/sqlite/__init__.py +1 -0
- flock_core-0.5.21/tests/storage/sqlite/test_agent_history_queries.py +329 -0
- flock_core-0.5.21/tests/storage/sqlite/test_consumption_loader.py +222 -0
- flock_core-0.5.21/tests/storage/sqlite/test_query_builder.py +161 -0
- flock_core-0.5.21/tests/storage/sqlite/test_query_params_builder.py +146 -0
- flock_core-0.5.21/tests/storage/sqlite/test_schema_manager.py +188 -0
- flock_core-0.5.21/tests/storage/sqlite/test_summary_queries.py +236 -0
- flock_core-0.5.21/tests/storage/test_artifact_aggregator.py +243 -0
- flock_core-0.5.21/tests/test_agent.py +564 -0
- flock_core-0.5.21/tests/test_agent_builder.py +1450 -0
- flock_core-0.5.21/tests/test_agent_mcp.py +97 -0
- flock_core-0.5.21/tests/test_agent_server_specific_mounts.py +184 -0
- flock_core-0.5.21/tests/test_api_models.py +339 -0
- flock_core-0.5.21/tests/test_artifacts.py +107 -0
- flock_core-0.5.21/tests/test_cli.py +556 -0
- flock_core-0.5.21/tests/test_cli_helper.py +346 -0
- flock_core-0.5.21/tests/test_components.py +523 -0
- flock_core-0.5.21/tests/test_context_provider.py +1305 -0
- flock_core-0.5.21/tests/test_context_security.py +328 -0
- flock_core-0.5.21/tests/test_dashboard_api.py +614 -0
- flock_core-0.5.21/tests/test_dashboard_collector.py +611 -0
- flock_core-0.5.21/tests/test_dashboard_graph.py +159 -0
- flock_core-0.5.21/tests/test_dashboard_service.py +1851 -0
- flock_core-0.5.21/tests/test_dspy_engine.py +1000 -0
- flock_core-0.5.21/tests/test_dspy_engine_mcp.py +103 -0
- flock_core-0.5.21/tests/test_dspy_engine_multioutput.py +1521 -0
- flock_core-0.5.21/tests/test_dspy_streaming_executor_helpers.py +216 -0
- flock_core-0.5.21/tests/test_dspy_streaming_integration.py +473 -0
- flock_core-0.5.21/tests/test_engine_context.py +288 -0
- flock_core-0.5.21/tests/test_engines.py +213 -0
- flock_core-0.5.21/tests/test_filtering_validation.py +624 -0
- flock_core-0.5.21/tests/test_mcp_server_config_typeddict.py +92 -0
- flock_core-0.5.21/tests/test_orchestrator.py +648 -0
- flock_core-0.5.21/tests/test_orchestrator_and_gate.py +1329 -0
- flock_core-0.5.21/tests/test_orchestrator_batchspec.py +635 -0
- flock_core-0.5.21/tests/test_orchestrator_combined.py +936 -0
- flock_core-0.5.21/tests/test_orchestrator_component.py +1415 -0
- flock_core-0.5.21/tests/test_orchestrator_context_injection.py +590 -0
- flock_core-0.5.21/tests/test_orchestrator_joinspec.py +914 -0
- flock_core-0.5.21/tests/test_orchestrator_mcp.py +131 -0
- flock_core-0.5.21/tests/test_output_groups.py +550 -0
- flock_core-0.5.21/tests/test_runtime.py +470 -0
- flock_core-0.5.21/tests/test_service.py +51 -0
- flock_core-0.5.21/tests/test_service_extended.py +445 -0
- flock_core-0.5.21/tests/test_store.py +394 -0
- flock_core-0.5.21/tests/test_store_graph.py +103 -0
- flock_core-0.5.21/tests/test_subscription.py +262 -0
- flock_core-0.5.21/tests/test_trace_clearing.py +315 -0
- flock_core-0.5.21/tests/test_unified_tracing.py +195 -0
- flock_core-0.5.21/tests/test_utilities.py +893 -0
- flock_core-0.5.21/tests/test_version_endpoint.py +66 -0
- flock_core-0.5.21/tests/test_visibility.py +217 -0
- flock_core-0.5.21/tests/utils/__init__.py +1 -0
- flock_core-0.5.21/tests/utils/test_async_utils.py +140 -0
- flock_core-0.5.21/tests/utils/test_time_utils.py +93 -0
- flock_core-0.5.21/tests/utils/test_type_resolution.py +55 -0
- flock_core-0.5.21/tests/utils/test_validation.py +199 -0
- flock_core-0.5.21/tests/utils/test_visibility.py +135 -0
- flock_core-0.5.21/tests/utils/test_visibility_utils.py +125 -0
- flock_core-0.5.21/uv.lock +4550 -0
- flock_core-0.5.11/AGENTS.md +0 -1764
- flock_core-0.5.11/CONTRIBUTING.md +0 -575
- flock_core-0.5.11/PKG-INFO +0 -1313
- flock_core-0.5.11/README.md +0 -1280
- flock_core-0.5.11/ROADMAP.md +0 -165
- flock_core-0.5.11/USECASES.md +0 -561
- flock_core-0.5.11/docs/about/changelog.md +0 -1088
- flock_core-0.5.11/docs/getting-started/quick-start.md +0 -596
- flock_core-0.5.11/docs/guides/batch-processing.md +0 -816
- flock_core-0.5.11/docs/guides/blackboard.md +0 -795
- flock_core-0.5.11/docs/guides/context-providers.md +0 -1515
- flock_core-0.5.11/docs/guides/fan-out.md +0 -1092
- flock_core-0.5.11/docs/guides/join-operations.md +0 -786
- flock_core-0.5.11/docs/guides/mcp-roots.md +0 -416
- flock_core-0.5.11/docs/guides/patterns.md +0 -1232
- flock_core-0.5.11/docs/guides/testing.md +0 -709
- flock_core-0.5.11/docs/guides/tracing/unified-tracing.md +0 -374
- flock_core-0.5.11/docs/guides/use-cases.md +0 -561
- flock_core-0.5.11/docs/guides/visibility.md +0 -890
- flock_core-0.5.11/docs/reference/index.md +0 -335
- flock_core-0.5.11/docs/tutorials/advanced-patterns.md +0 -437
- flock_core-0.5.11/docs/tutorials/conditional-routing.md +0 -334
- flock_core-0.5.11/docs/tutorials/connect_with_ollama.md +0 -255
- flock_core-0.5.11/docs/tutorials/multi-agent-workflow.md +0 -383
- flock_core-0.5.11/docs/tutorials/your-first-agent.md +0 -229
- flock_core-0.5.11/examples/00-patterns/01-single_publish.py +0 -45
- flock_core-0.5.11/examples/00-patterns/02-multi_publish.py +0 -66
- flock_core-0.5.11/examples/00-patterns/03-multi-artifact-multi-publish.py +0 -68
- flock_core-0.5.11/examples/00-patterns/04-fan-out.py +0 -38
- flock_core-0.5.11/examples/00-patterns/05-multi-fan-out.py +0 -70
- flock_core-0.5.11/examples/01-cli/01_declarative_pizza.py +0 -36
- flock_core-0.5.11/examples/01-cli/02_input_and_output.py +0 -54
- flock_core-0.5.11/examples/01-cli/03_code_detective.py +0 -70
- flock_core-0.5.11/examples/01-cli/04_input_and_output.py +0 -83
- flock_core-0.5.11/examples/01-cli/05_mcp_and_tools.py +0 -116
- flock_core-0.5.11/examples/01-cli/06_mcp_roots.py +0 -115
- flock_core-0.5.11/examples/01-cli/07_web_detective.py +0 -119
- flock_core-0.5.11/examples/01-cli/08_band_formation.py +0 -90
- flock_core-0.5.11/examples/01-cli/09_debate_club.py +0 -108
- flock_core-0.5.11/examples/01-cli/10_news_agency.py +0 -98
- flock_core-0.5.11/examples/01-cli/11_tracing_detective.py +0 -91
- flock_core-0.5.11/examples/01-cli/12_secret_agents.py +0 -98
- flock_core-0.5.11/examples/01-cli/13_medical_diagnostics_joinspec.py +0 -156
- flock_core-0.5.11/examples/01-cli/14_ecommerce_batch_processing.py +0 -148
- flock_core-0.5.11/examples/01-cli/15_iot_sensor_batching.py +0 -193
- flock_core-0.5.11/examples/01-cli/README.md +0 -290
- flock_core-0.5.11/examples/02-dashboard/01_declarative_pizza.py +0 -29
- flock_core-0.5.11/examples/02-dashboard/02_input_and_output.py +0 -31
- flock_core-0.5.11/examples/02-dashboard/02_non_blocking_serve.py +0 -97
- flock_core-0.5.11/examples/02-dashboard/03_code_detective.py +0 -37
- flock_core-0.5.11/examples/02-dashboard/04_input_and_output.py +0 -77
- flock_core-0.5.11/examples/02-dashboard/05_mcp_and_tools.py +0 -93
- flock_core-0.5.11/examples/02-dashboard/06_mcp_roots.py +0 -82
- flock_core-0.5.11/examples/02-dashboard/07_web_detective.py +0 -74
- flock_core-0.5.11/examples/02-dashboard/08_band_formation.py +0 -65
- flock_core-0.5.11/examples/02-dashboard/09_debate_club.py +0 -82
- flock_core-0.5.11/examples/02-dashboard/10_news_agency.py +0 -72
- flock_core-0.5.11/examples/02-dashboard/11_tracing_detective.py +0 -53
- flock_core-0.5.11/examples/02-dashboard/12_secret_agents.py +0 -67
- flock_core-0.5.11/examples/02-dashboard/13_medical_diagnostics_joinspec.py +0 -92
- flock_core-0.5.11/examples/02-dashboard/14_ecommerce_batch_processing.py +0 -69
- flock_core-0.5.11/examples/02-dashboard/15_iot_sensor_batching.py +0 -84
- flock_core-0.5.11/examples/02-dashboard/16_news_batching.py +0 -83
- flock_core-0.5.11/examples/02-dashboard/README.md +0 -235
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_01_code_detective.py +0 -71
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_02_band_formation.py +0 -99
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_03_web_detective.py +0 -116
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_04_debate_club.py +0 -103
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_05_tracing_detective.py +0 -123
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_06_secret_agents.py +0 -117
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_07_news_agency.py +0 -142
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_08_the_matchmaker.py +0 -222
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_09_the_batch_optimizer.py +0 -226
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_10_the_smart_factory.py +0 -307
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_11_performance_monitor.py +0 -357
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_12_confidence_booster.py +0 -358
- flock_core-0.5.11/examples/03-claudes-workshop/lesson_13_regex_matcher.py +0 -302
- flock_core-0.5.11/examples/04-misc/01_persistent_pizza.py +0 -128
- flock_core-0.5.11/examples/04-misc/02-dashboard-edge-cases.py +0 -95
- flock_core-0.5.11/examples/04-misc/03-scale-test-100-agents.py +0 -130
- flock_core-0.5.11/examples/04-misc/04_persistent_pizza_dashboard.py +0 -108
- flock_core-0.5.11/examples/04-misc/05_lm_studio.py +0 -35
- flock_core-0.5.11/examples/05-engines/emoji_mood_engine.py +0 -139
- flock_core-0.5.11/examples/05-engines/potion_batch_engine.py +0 -161
- flock_core-0.5.11/examples/06-agent-components/cheer_meter_component.py +0 -118
- flock_core-0.5.11/examples/06-agent-components/plot_twist_component.py +0 -138
- flock_core-0.5.11/examples/07-orchestrator-components/kitchen_monitor_component.py +0 -209
- flock_core-0.5.11/examples/07-orchestrator-components/quest_tracker_component.py +0 -175
- flock_core-0.5.11/examples/08-context-provider/01_basic_visibility.py +0 -144
- flock_core-0.5.11/examples/08-context-provider/02_global_provider.py +0 -192
- flock_core-0.5.11/examples/08-context-provider/02_simple_global_provider.py +0 -49
- flock_core-0.5.11/examples/08-context-provider/03_per_agent_provider.py +0 -233
- flock_core-0.5.11/examples/08-context-provider/04_custom_filtering.py +0 -247
- flock_core-0.5.11/examples/08-context-provider/05_password_redactor.py +0 -435
- flock_core-0.5.11/examples/08-context-provider/README.md +0 -502
- flock_core-0.5.11/examples/README.md +0 -298
- flock_core-0.5.11/pyproject.toml +0 -158
- flock_core-0.5.11/src/flock/__init__.py +0 -16
- flock_core-0.5.11/src/flock/agent.py +0 -1578
- flock_core-0.5.11/src/flock/api_models.py +0 -285
- flock_core-0.5.11/src/flock/artifact_collector.py +0 -161
- flock_core-0.5.11/src/flock/artifacts.py +0 -86
- flock_core-0.5.11/src/flock/batch_accumulator.py +0 -254
- flock_core-0.5.11/src/flock/cli.py +0 -149
- flock_core-0.5.11/src/flock/components.py +0 -222
- flock_core-0.5.11/src/flock/context_provider.py +0 -531
- flock_core-0.5.11/src/flock/correlation_engine.py +0 -224
- flock_core-0.5.11/src/flock/dashboard/collector.py +0 -584
- flock_core-0.5.11/src/flock/dashboard/events.py +0 -268
- flock_core-0.5.11/src/flock/dashboard/graph_builder.py +0 -835
- flock_core-0.5.11/src/flock/dashboard/service.py +0 -1434
- flock_core-0.5.11/src/flock/engines/dspy_engine.py +0 -1797
- flock_core-0.5.11/src/flock/engines/examples/simple_batch_engine.py +0 -83
- flock_core-0.5.11/src/flock/examples.py +0 -135
- flock_core-0.5.11/src/flock/logging/logging.py +0 -591
- flock_core-0.5.11/src/flock/orchestrator.py +0 -1983
- flock_core-0.5.11/src/flock/orchestrator_component.py +0 -696
- flock_core-0.5.11/src/flock/runtime.py +0 -316
- flock_core-0.5.11/src/flock/service.py +0 -348
- flock_core-0.5.11/src/flock/store.py +0 -1233
- flock_core-0.5.11/src/flock/subscription.py +0 -176
- flock_core-0.5.11/src/flock/utilities.py +0 -329
- flock_core-0.5.11/src/flock/utility/output_utility_component.py +0 -246
- flock_core-0.5.11/tests/conftest.py +0 -142
- flock_core-0.5.11/tests/contract/test_agent_payload_selection_contract.py +0 -174
- flock_core-0.5.11/tests/contract/test_artifact_storage_contract.py +0 -139
- flock_core-0.5.11/tests/dashboard/test_logic_operations_api.py +0 -1108
- flock_core-0.5.11/tests/dashboard/test_logic_operations_events.py +0 -614
- flock_core-0.5.11/tests/e2e/test_critical_scenarios.py +0 -677
- flock_core-0.5.11/tests/integration/test_collector_orchestrator.py +0 -349
- flock_core-0.5.11/tests/integration/test_orchestrator_dashboard.py +0 -615
- flock_core-0.5.11/tests/integration/test_sqlite_store_integration.py +0 -37
- flock_core-0.5.11/tests/integration/test_websocket_protocol.py +0 -496
- flock_core-0.5.11/tests/test_agent.py +0 -533
- flock_core-0.5.11/tests/test_agent_builder.py +0 -1499
- flock_core-0.5.11/tests/test_agent_mcp.py +0 -97
- flock_core-0.5.11/tests/test_agent_server_specific_mounts.py +0 -237
- flock_core-0.5.11/tests/test_api_models.py +0 -320
- flock_core-0.5.11/tests/test_artifacts.py +0 -104
- flock_core-0.5.11/tests/test_cli.py +0 -550
- flock_core-0.5.11/tests/test_cli_helper.py +0 -346
- flock_core-0.5.11/tests/test_components.py +0 -513
- flock_core-0.5.11/tests/test_context_provider.py +0 -1266
- flock_core-0.5.11/tests/test_context_security.py +0 -325
- flock_core-0.5.11/tests/test_dashboard_api.py +0 -610
- flock_core-0.5.11/tests/test_dashboard_collector.py +0 -603
- flock_core-0.5.11/tests/test_dashboard_graph.py +0 -161
- flock_core-0.5.11/tests/test_dashboard_service.py +0 -1857
- flock_core-0.5.11/tests/test_dspy_engine.py +0 -1060
- flock_core-0.5.11/tests/test_dspy_engine_mcp.py +0 -98
- flock_core-0.5.11/tests/test_dspy_engine_multioutput.py +0 -1476
- flock_core-0.5.11/tests/test_engine_context.py +0 -283
- flock_core-0.5.11/tests/test_engines.py +0 -201
- flock_core-0.5.11/tests/test_filtering_validation.py +0 -593
- flock_core-0.5.11/tests/test_mcp_server_config_typeddict.py +0 -128
- flock_core-0.5.11/tests/test_orchestrator.py +0 -562
- flock_core-0.5.11/tests/test_orchestrator_and_gate.py +0 -1059
- flock_core-0.5.11/tests/test_orchestrator_batchspec.py +0 -641
- flock_core-0.5.11/tests/test_orchestrator_combined.py +0 -876
- flock_core-0.5.11/tests/test_orchestrator_component.py +0 -1321
- flock_core-0.5.11/tests/test_orchestrator_context_injection.py +0 -578
- flock_core-0.5.11/tests/test_orchestrator_joinspec.py +0 -897
- flock_core-0.5.11/tests/test_orchestrator_mcp.py +0 -131
- flock_core-0.5.11/tests/test_output_groups.py +0 -600
- flock_core-0.5.11/tests/test_runtime.py +0 -470
- flock_core-0.5.11/tests/test_service.py +0 -51
- flock_core-0.5.11/tests/test_service_extended.py +0 -430
- flock_core-0.5.11/tests/test_store.py +0 -391
- flock_core-0.5.11/tests/test_store_graph.py +0 -105
- flock_core-0.5.11/tests/test_subscription.py +0 -256
- flock_core-0.5.11/tests/test_trace_clearing.py +0 -315
- flock_core-0.5.11/tests/test_unified_tracing.py +0 -195
- flock_core-0.5.11/tests/test_utilities.py +0 -858
- flock_core-0.5.11/tests/test_version_endpoint.py +0 -62
- flock_core-0.5.11/tests/test_visibility.py +0 -215
- flock_core-0.5.11/uv.lock +0 -4523
- {flock_core-0.5.11 → flock_core-0.5.21}/.devcontainer/devcontainer.json +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.envtemplate +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.github/issue_draft_non_blocking_serve.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.github/workflows/deploy-documentation.yml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.github/workflows/deploy-whiteduck-pypi.yml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.github/workflows/quality.yml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.gitignore +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.pre-commit-config.yaml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.python-version +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/.vscode/settings.json +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/AUTO_TRACING.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/ID_AUDIT_REPORT.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/LICENSE +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/about/contributing.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/about/roadmap.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/batch.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/bug_diagnosis.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/flock.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/flock_ui_1.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/flock_ui_agent_view.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/flock_ui_blackboard_view.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/join.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/pattern2.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/pizza.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/trace_1.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/trace_2.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/assets/images/trace_3.png +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/bugfixes/websocket-streaming-deadlock-fix.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/community/index.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/examples/index.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/getting-started/concepts.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/getting-started/index.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/getting-started/installation.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/agents.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/components.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/dashboard.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/dspy-engine.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/index.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/orchestrator-components.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/persistent-blackboard.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/predicates.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/rest-api.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/tracing/auto-tracing.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/tracing/how_to_use_tracing_effectively.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/tracing/index.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/tracing/trace-module.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/tracing/tracing-production.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/guides/tracing/tracing-quickstart.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/index.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/javascripts/extra.js +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/reference/api.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/reference/configuration.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/stylesheets/extra.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/tags.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/troubleshooting/streaming-freeze-fix.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/troubleshooting/streaming-freeze-with-dashboard-fix.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/tutorials/custom-agent-components.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/tutorials/custom-engines.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/tutorials/index.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/docs/whiteducksoftware/versions.json +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/examples/00-patterns/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/examples/03-claudes-workshop/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/examples/04-misc/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/examples/05-engines/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/examples/06-agent-components/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/examples/07-orchestrator-components/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/mkdocs.yml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/requirements.txt +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/scripts/build_dashboard.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/scripts/bump_version.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/scripts/check_version_bump.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/scripts/ensure_uv.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/scripts/gen_ref_pages.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/scripts/generate_llm_codebase.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/api/themes.py +0 -0
- {flock_core-0.5.11/src/flock → flock_core-0.5.21/src/flock/core}/visibility.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/launcher.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/models/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/models/graph.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/static_v2/assets/index-DFRnI_mt.js +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/static_v2/assets/index-fPLNdmp1.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/static_v2/index.html +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/dashboard/websocket.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/engines/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/engines/examples/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/docs/DESIGN_SYSTEM.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/index.html +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/package-lock.json +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/package.json +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/App.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/BuildInfo.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/EmptyState.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/EmptyState.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/ErrorBoundary.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/ErrorBoundary.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/KeyboardShortcutsDialog.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/LoadingSpinner.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/common/LoadingSpinner.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/controls/PublishControl.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/controls/PublishControl.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/controls/PublishControl.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/DetailWindowContainer.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/LiveOutputTab.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/LiveOutputTab.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/MessageDetailWindow.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/MessageHistoryTab.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/NodeDetailWindow.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/NodeDetailWindow.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/RunStatusTab.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/details/tabs.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/ArtifactTypeFilter.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/CorrelationIDFilter.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/CorrelationIDFilter.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/FilterFlyout.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/FilterFlyout.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/FilterPills.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/FilterPills.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/FilterPills.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/ProducerFilter.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/SavedFiltersControl.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/SavedFiltersControl.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/SavedFiltersControl.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/TagFilter.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/TimeRangeFilter.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/TimeRangeFilter.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/filters/VisibilityFilter.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/AgentNode.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/AgentNode.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/GraphCanvas.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/LogicOperationsDisplay.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/MessageFlowEdge.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/MessageNode.test.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/MessageNode.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/MiniMap.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/PendingBatchEdge.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/PendingJoinEdge.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/graph/TransformEdge.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/layout/DashboardLayout.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/layout/DashboardLayout.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/layout/Header.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/layout/Header.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/HistoricalArtifactsModule.module.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/HistoricalArtifactsModuleWrapper.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/JsonAttributeRenderer.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/ModuleRegistry.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/ModuleRegistry.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/ModuleWindow.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/TraceModuleJaeger.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/TraceModuleJaegerWrapper.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/modules/registerModules.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/AdvancedSettings.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/AppearanceSettings.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/GraphSettings.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/MultiSelect.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/SettingsPanel.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/SettingsPanel.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/ThemeSelector.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/components/settings/TracingSettings.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/hooks/useKeyboardShortcuts.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/hooks/useModulePersistence.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/hooks/useModulePersistence.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/hooks/useModules.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/hooks/usePersistence.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/main.tsx +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/api.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/graphService.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/graphService.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/indexeddb.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/indexeddb.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/layout.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/layout.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/themeApplicator.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/themeService.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/services/websocket.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/filterStore.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/filterStore.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/graphStore.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/graphStore.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/moduleStore.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/moduleStore.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/settingsStore.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/streamStore.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/uiStore.test.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/uiStore.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/store/wsStore.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/styles/index.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/styles/scrollbar.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/styles/variables.css +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/test/setup.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/types/filters.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/types/graph.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/types/modules.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/types/theme.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/utils/artifacts.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/utils/mockData.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/utils/performance.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/src/vite-env.d.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/tsconfig.json +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/tsconfig.node.json +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/vite.config.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/frontend/vitest.config.ts +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/auto_trace.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/formatters/enum_builder.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/formatters/theme_builder.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/formatters/themed_formatter.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/formatters/themes.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/span_middleware/baggage_span_processor.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/telemetry.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/telemetry_exporter/base_exporter.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/telemetry_exporter/duckdb_exporter.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/telemetry_exporter/file_exporter.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/telemetry_exporter/sqlite_exporter.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/logging/trace_and_logged.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/client.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/config.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/manager.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/sse/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/sse/flock_sse_server.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/stdio/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/stdio/flock_stdio_server.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/streamable_http/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/streamable_http/flock_streamable_http_server.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/websockets/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/servers/websockets/flock_websocket_server.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/tool.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/types/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/types/callbacks.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/types/factories.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/types/handlers.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/types/types.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/util/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/mcp/util/helpers.py +0 -0
- {flock_core-0.5.11/src/flock → flock_core-0.5.21/src/flock/models}/system_artifacts.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/patches/__init__.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/patches/dspy_streaming_patch.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/registry.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/3024-day.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/3024-night.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/aardvark-blue.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/abernathy.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/adventure.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/adventuretime.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/afterglow.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/alabaster.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/alienblood.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/andromeda.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/apple-classic.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/apple-system-colors.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/arcoiris.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/argonaut copy.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/argonaut.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/arthur.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ateliersulphurpool.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/atom.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/atom_test.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/atomonelight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/aurora.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ayu copy.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ayu-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ayu-mirage.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ayu.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/banana-blueberry.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/batman.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/belafonte-day.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/belafonte-night.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/birdsofparadise.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/blazer.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/blue-matrix.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/blueberrypie.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/bluedolphin.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/blulocodark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/blulocolight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/borland.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/breeze.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/bright-lights.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/broadcast.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/brogrammer.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/builtin-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/builtin-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/builtin-pastel-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/builtin-solarized-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/builtin-solarized-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/builtin-tango-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/builtin-tango-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/c64.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/calamity.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/catppuccin-frappe.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/catppuccin-latte.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/catppuccin-macchiato.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/catppuccin-mocha.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/cga.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/chalk.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/chalkboard.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/challengerdeep.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/chester.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ciapre.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/clrs.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/cobalt-neon.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/cobalt2.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/coffee-theme.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/crayonponyfish.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/cutiepro.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/cyberdyne.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/cyberpunk.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/cyberpunkscarletprotocol.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dark+.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dark-pastel.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/darkermatrix.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/darkmatrix.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/darkside.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dayfox.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/deep.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/desert.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dimidium.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dimmedmonokai.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/django.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/djangorebornagain.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/djangosmooth.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/doom-peacock.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/doomone.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dotgov.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dracula+.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/dracula.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/duckbones.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/duotone-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/earthsong.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/elemental.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/elementary.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/encom.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/espresso-libre.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/espresso.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/everblush.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/fahrenheit.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/fairyfloss.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/farmhouse-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/farmhouse-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/fideloper.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/firefly-traditional.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/firefoxdev.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/firewatch.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/fishtank.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/flat.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/flatland.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/flexoki-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/flexoki-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/floraverse.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/forestblue.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/framer.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/frontenddelight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/funforrest.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/galaxy.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/galizur.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/github-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/github.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/glacier.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/grape.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/grass.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/grey-green.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/gruber-darker.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/gruvboxdark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/gruvboxdarkhard.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/gruvboxlight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/guezwhoz.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hacktober.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hardcore.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/harper.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hax0r-blue.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hax0r-gr33n.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hax0r-r3d.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/highway.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hipster-green.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hivacruz.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/homebrew.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hopscotch.256.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hopscotch.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hurtado.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/hybrid.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ic-green-ppl.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ic-orange-ppl.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iceberg-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iceberg-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/idea.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/idletoes.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ir-black.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-dark-background.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-default.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-light-background.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-pastel-dark-background.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-smoooooth.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-solarized-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-solarized-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-tango-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/iterm2-tango-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/jackie-brown.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/japanesque.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/jellybeans.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/jetbrains-darcula.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/jubi.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/kanagawabones.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/kibble.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/kolorit.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/konsolas.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/kurokula.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/lab-fox.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/laser.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/later-this-evening.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/lavandula.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/liquidcarbon.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/liquidcarbontransparent.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/liquidcarbontransparentinverse.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/lovelace.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/man-page.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/mariana.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/material.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/materialdark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/materialdarker.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/materialdesigncolors.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/materialocean.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/mathias.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/matrix.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/medallion.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/mellifluous.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/midnight-in-mojave.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/mirage.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/misterioso.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/molokai.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/monalisa.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/monokai-remastered.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/monokai-soda.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/monokai-vivid.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/n0tch2k.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/neobones-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/neobones-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/neon.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/neopolitan.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/neutron.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/night-owlish-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nightfox.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nightlion-v1.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nightlion-v2.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/niji.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nocturnal-winter.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nord-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nord.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/novel.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nvimdark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/nvimlight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/obsidian.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ocean.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/oceanic-next.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/oceanicmaterial.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ollie.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/onehalfdark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/onehalflight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/operator-mono-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/overnight-slumber.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/oxocarbon.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/palenighthc.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/pandora.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/paraiso-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/paulmillr.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/pencildark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/pencillight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/peppermint.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/piatto-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/pnevma.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/popping-and-locking.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/primary.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/pro-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/pro.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/purple-rain.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/purplepeter.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/rapture.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/raycast-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/raycast-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/rebecca.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/red-alert.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/red-planet.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/red-sands.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/relaxed.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/retro.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/rippedcasts.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/rose-pine-dawn.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/rose-pine-moon.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/rose-pine.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/rouge-2.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/royal.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ryuuko.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/sakura.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/scarlet-protocol.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/seafoam-pastel.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/seashells.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/seoulbones-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/seoulbones-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/seti.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/shades-of-purple.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/shaman.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/slate.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/sleepyhollow.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/smyck.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/snazzy.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/softserver.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/solarized-darcula.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/solarized-dark---patched.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/solarized-dark-higher-contrast.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/spacedust.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/spacegray-eighties-dull.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/spacegray-eighties.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/spacegray.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/spiderman.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/spring.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/square.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/sublette.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/subliminal.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/sugarplum.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/sundried.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/symfonic.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/synthwave-everything.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/synthwave.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/synthwavealpha.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tango-adapted.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tango-half-adapted.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/teerb.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/terafox.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/terminal-basic.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/thayer-bright.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/the-hulk.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tinacious-design-(dark).toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tinacious-design-(light).toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tokyonight-day.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tokyonight-storm.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tokyonight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tomorrow-night-blue.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tomorrow-night-bright.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tomorrow-night-burns.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tomorrow-night-eighties.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tomorrow-night.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/tomorrow.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/toychest.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/treehouse.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/twilight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ubuntu.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ultradark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/ultraviolent.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/underthesea.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/unikitty.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/urple.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/vaughn.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/vesper.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/vibrantink.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/vimbones.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/violet-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/violet-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/warmneon.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/wez.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/whimsy.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/wildcherry.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/wilmersdorf.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/wombat.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/wryan.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/xcodedark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/xcodedarkhc.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/xcodelight.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/xcodelighthc.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/xcodewwdc.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/zenbones-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/zenbones-light.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/zenbones.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/zenburn.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/zenburned.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/zenwritten-dark.toml +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/src/flock/themes/zenwritten-light.toml +0 -0
- {flock_core-0.5.11/src/flock/helper → flock_core-0.5.21/src/flock/utils}/cli_helper.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/PHASE2_TEST_SUMMARY.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/PHASE3_TEST_SUMMARY.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/TEST_COVERAGE_PHASE2.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/contract/test_type_normalization_contract.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/e2e/README.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/e2e/TESTING_SUMMARY.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_dashboard_launcher.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_dspy_streaming_events.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_logging_config.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_mcp_client.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_mcp_config.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_mcp_coverage_summary.md +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_mcp_imports.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_mcp_manager.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_mcp_tool_handlers.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_registry.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_telemetry.py +0 -0
- {flock_core-0.5.11 → flock_core-0.5.21}/tests/test_websocket_manager.py +0 -0
|
@@ -0,0 +1,1789 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
**Welcome, AI coding agent!** 👋
|
|
4
|
+
|
|
5
|
+
This is Flock, a production-grade blackboard-first AI agent orchestration framework. This guide gets you up to speed quickly on the current project state and development patterns.
|
|
6
|
+
|
|
7
|
+
**Current Version:** Backend: 0.5.0b63 • Frontend: 0.1.4
|
|
8
|
+
**Architecture:** Hybrid Python/TypeScript with real-time dashboard
|
|
9
|
+
**Package Manager:** UV (NOT pip!)
|
|
10
|
+
**Status:** Production-ready with comprehensive monitoring
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🎯 Project Snapshot
|
|
15
|
+
|
|
16
|
+
### What Is Flock?
|
|
17
|
+
|
|
18
|
+
A blackboard architecture framework where specialized AI agents collaborate through a shared typed workspace—no direct coupling, no rigid workflows, just emergent intelligence.
|
|
19
|
+
|
|
20
|
+
**Core Pattern:** Blackboard Architecture (like Hearsay-II from 1970s, but for modern LLMs)
|
|
21
|
+
|
|
22
|
+
**Key Differentiator:** The only framework treating blackboard orchestration as a first-class citizen with built-in visibility controls, real-time monitoring, and enterprise-grade safety features.
|
|
23
|
+
|
|
24
|
+
### Architecture in 30 Seconds
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
┌─────────────────────────────────────────────┐
|
|
28
|
+
│ Blackboard (Typed Artifacts) │
|
|
29
|
+
│ ┌──────┐ → ┌──────┐ → ┌──────┐ → ┌──────┐│
|
|
30
|
+
│ │ Idea │ │Movie │ │Script│ │Review││
|
|
31
|
+
│ └──────┘ └──────┘ └──────┘ └──────┘│
|
|
32
|
+
└─────────────────────────────────────────────┘
|
|
33
|
+
↑ ↑ ↑ ↑
|
|
34
|
+
Agent A Agent B Agent C Agent D
|
|
35
|
+
(produce) (consume (consume (consume
|
|
36
|
+
& produce) & produce) & produce)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Key Concepts:**
|
|
40
|
+
- **Artifacts:** Typed data (Pydantic models) published to blackboard
|
|
41
|
+
- **Subscriptions:** Declarative rules for when agents react
|
|
42
|
+
- **Visibility:** Built-in access control (Public/Private/Tenant/Label-based/Time-based)
|
|
43
|
+
- **Fan-Out Publishing:** Produce multiple artifacts from single agent execution with filtering/validation
|
|
44
|
+
- **Components:** Three levels of extensibility:
|
|
45
|
+
- **Orchestrator Components:** Global lifecycle hooks (monitoring, metrics, coordination)
|
|
46
|
+
- **Agent Components:** Per-agent behavior (quality gates, retry logic, validation)
|
|
47
|
+
- **Engines:** Custom processing logic (DSPy, regex, deterministic rules)
|
|
48
|
+
- **Real-time Dashboard:** React/TypeScript interface for live monitoring
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚀 Quick Setup
|
|
53
|
+
|
|
54
|
+
### Prerequisites
|
|
55
|
+
|
|
56
|
+
- **Python 3.12+** (we use modern async features)
|
|
57
|
+
- **UV package manager** (faster than pip, handles virtual envs)
|
|
58
|
+
- **Node.js 18+** (22+ recommended) for dashboard frontend
|
|
59
|
+
- **OpenAI API key** (for running examples)
|
|
60
|
+
|
|
61
|
+
### Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Clone repo
|
|
65
|
+
git clone https://github.com/yourusername/flock-flow.git
|
|
66
|
+
cd flock-flow
|
|
67
|
+
|
|
68
|
+
# Install Python dependencies (UV creates venv automatically)
|
|
69
|
+
poe install # Equivalent to: uv sync --dev --all-groups --all-extras
|
|
70
|
+
|
|
71
|
+
# Set up environment
|
|
72
|
+
export OPENAI_API_KEY="sk-..."
|
|
73
|
+
export DEFAULT_MODEL="openai/gpt-4.1"
|
|
74
|
+
|
|
75
|
+
# Verify installation
|
|
76
|
+
uv run python -c "from flock import Flock; print('✅ Ready!')"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Run Examples
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# CLI examples (with detailed output)
|
|
83
|
+
uv run python examples/01-cli/01_declarative_pizza.py
|
|
84
|
+
uv run python examples/01-cli/02_input_and_output.py
|
|
85
|
+
uv run python examples/01-cli/03_code_detective.py
|
|
86
|
+
|
|
87
|
+
# Dashboard examples (with visualization)
|
|
88
|
+
uv run python examples/02-dashboard/01_declarative_pizza.py
|
|
89
|
+
uv run python examples/02-dashboard/02_input_and_output.py
|
|
90
|
+
uv run python examples/02-dashboard/03_code_detective.py
|
|
91
|
+
|
|
92
|
+
# Engine + component playgrounds
|
|
93
|
+
uv run python examples/05-engines/emoji_mood_engine.py
|
|
94
|
+
uv run python examples/05-engines/potion_batch_engine.py
|
|
95
|
+
uv run python examples/06-agent-components/plot_twist_component.py
|
|
96
|
+
uv run python examples/06-agent-components/cheer_meter_component.py
|
|
97
|
+
uv run python examples/07-orchestrator-components/quest_tracker_component.py
|
|
98
|
+
uv run python examples/07-orchestrator-components/kitchen_monitor_component.py
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 📚 Detailed Guides
|
|
104
|
+
|
|
105
|
+
For deep dives into specific topics, see:
|
|
106
|
+
|
|
107
|
+
**Core Architecture:**
|
|
108
|
+
- **[Architecture Overview](docs/architecture.md)** - Complete system design, module organization, and Phase 1-7 refactoring ⭐ **UPDATED**
|
|
109
|
+
- **[Architecture & Blackboard](docs/guides/blackboard.md)** - Core pattern, structure, and behavior
|
|
110
|
+
- **[Agent Guide](docs/guides/agents.md)** - Complete agent development reference
|
|
111
|
+
- **[Context Providers](docs/guides/context-providers.md)** - Smart filtering & security boundaries for agent context ⭐ **NEW in 0.5**
|
|
112
|
+
|
|
113
|
+
**Code Patterns & Standards:**
|
|
114
|
+
- **[Error Handling Patterns](docs/patterns/error_handling.md)** - Production-ready error handling guide ⭐ **NEW**
|
|
115
|
+
- **[Async Patterns](docs/patterns/async_patterns.md)** - Async/await best practices and common pitfalls ⭐ **NEW**
|
|
116
|
+
|
|
117
|
+
**Components & Extensibility:**
|
|
118
|
+
- **[Agent Components](docs/guides/components.md)** - Extend agent behavior with lifecycle hooks
|
|
119
|
+
- **[Orchestrator Components](docs/guides/orchestrator-components.md)** - Extend orchestrator behavior with lifecycle hooks (NEW!)
|
|
120
|
+
|
|
121
|
+
**Logic Operations (Advanced Subscriptions):**
|
|
122
|
+
- **[Predicates](docs/guides/predicates.md)** - Conditional consumption with `where=` filters
|
|
123
|
+
- **[Join Operations](docs/guides/join-operations.md)** - Correlate related artifacts with JoinSpec
|
|
124
|
+
- **[Batch Processing](docs/guides/batch-processing.md)** - Efficient bulk operations with BatchSpec
|
|
125
|
+
|
|
126
|
+
**Publishing Patterns:**
|
|
127
|
+
- **[Fan-Out Publishing](docs/guides/fan-out.md)** - Generate multiple outputs with filtering/validation ⭐ **NEW in 0.5**
|
|
128
|
+
|
|
129
|
+
**Development & Operations:**
|
|
130
|
+
- **[Development Workflow](docs/guides/testing.md)** - Testing, quality, versioning, pre-commit
|
|
131
|
+
- **[Frontend/Dashboard](docs/guides/dashboard.md)** - Dashboard usage and development
|
|
132
|
+
- **[Configuration & Dependencies](CONTRIBUTING.md)** - Environment and setup
|
|
133
|
+
- **[Patterns & Common Tasks](docs/guides/patterns.md)** - Recipes, performance, security
|
|
134
|
+
- **[Development Workflow](docs/about/contributing.md)** - Testing, quality, versioning, pre-commit
|
|
135
|
+
- **[Frontend/Dashboard](docs/guides/dashboard.md)** - Dashboard usage and development
|
|
136
|
+
- **[Configuration & Dependencies](docs/reference/configuration.md)** - Environment and setup
|
|
137
|
+
- **[Patterns & Common Tasks](docs/guides/patterns.md)** - Recipes, performance, security
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 🚨 CRITICAL PATTERNS (Learn from Our Experience)
|
|
142
|
+
|
|
143
|
+
### ⚡ invoke() vs run_until_idle() - Execution Control (no double-run by default)
|
|
144
|
+
|
|
145
|
+
**This pattern cost us hours of debugging - learn from our pain!**
|
|
146
|
+
|
|
147
|
+
#### The Goal
|
|
148
|
+
Choose between isolated agent execution and event-driven cascades.
|
|
149
|
+
|
|
150
|
+
#### How it works
|
|
151
|
+
`invoke()` behavior depends on `publish_outputs`:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
# Isolated: execute agent only (no cascade)
|
|
155
|
+
await orchestrator.invoke(agent, input_artifact, publish_outputs=False)
|
|
156
|
+
|
|
157
|
+
# Cascading: execute and publish outputs, then run downstream agents
|
|
158
|
+
await orchestrator.invoke(agent, input_artifact, publish_outputs=True)
|
|
159
|
+
await orchestrator.run_until_idle() # processes downstream agents
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Notes:
|
|
163
|
+
- By default, agents have `prevent_self_trigger=True`, so an agent will not re-run on its own outputs when you call `run_until_idle()`. Downstream agents that subscribe to the output types will run.
|
|
164
|
+
|
|
165
|
+
#### When to Use Which Pattern
|
|
166
|
+
|
|
167
|
+
**✅ USE `publish_outputs=False` for:**
|
|
168
|
+
- Unit testing specific agent behavior
|
|
169
|
+
- Testing component hooks in isolation
|
|
170
|
+
- Direct execution without cascade
|
|
171
|
+
- Most test scenarios
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# ✅ CORRECT: Test component execution order
|
|
175
|
+
await orchestrator.invoke(agent, input_artifact, publish_outputs=False)
|
|
176
|
+
assert component_order == ["A", "B", "C"]
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**✅ USE `publish_outputs=True` + `run_until_idle()` for:**
|
|
180
|
+
- Integration testing agent cascades
|
|
181
|
+
- Testing multi-agent workflows
|
|
182
|
+
- End-to-end scenario validation
|
|
183
|
+
- Event-driven behavior testing
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
# ✅ CORRECT: Test agent cascade
|
|
187
|
+
await orchestrator.invoke(agent_a, input_artifact, publish_outputs=True)
|
|
188
|
+
await orchestrator.run_until_idle() # Process agent_b, agent_c...
|
|
189
|
+
assert len(output_artifacts) == 3
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Quick Reference
|
|
193
|
+
|
|
194
|
+
| Scenario | invoke() call | run_until_idle() | Result |
|
|
195
|
+
|----------|---------------|------------------|--------|
|
|
196
|
+
| Unit test | `invoke(..., publish_outputs=False)` | No | Single execution |
|
|
197
|
+
| Integration test | `invoke(..., publish_outputs=True)` | Yes | Cascade to downstream agents |
|
|
198
|
+
| Common mistake | `invoke(..., publish_outputs=True)` | Yes | Not a double-run; downstream agents run |
|
|
199
|
+
|
|
200
|
+
Rule of thumb: start with `publish_outputs=False` for unit tests; enable publication only when you want cascades.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### ⚡ Batching Pattern: publish() + run_until_idle() Separation = Parallel Power
|
|
205
|
+
|
|
206
|
+
**Why `run_until_idle()` is separate from `publish()` - it's not a bug, it's a feature!**
|
|
207
|
+
|
|
208
|
+
#### Sequential vs Parallel Execution
|
|
209
|
+
|
|
210
|
+
**❌ If `run_until_idle()` was built into `publish()`:**
|
|
211
|
+
```python
|
|
212
|
+
# Hypothetical auto-run design
|
|
213
|
+
await flock.publish(review1) # Publishes AND waits for completion
|
|
214
|
+
await flock.publish(review2) # Publishes AND waits for completion
|
|
215
|
+
await flock.publish(review3) # Publishes AND waits for completion
|
|
216
|
+
|
|
217
|
+
# Result: SEQUENTIAL processing (3x time)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**✅ With current design (separated):**
|
|
221
|
+
```python
|
|
222
|
+
# Queue up multiple artifacts
|
|
223
|
+
await flock.publish(review1) # Schedules agents
|
|
224
|
+
await flock.publish(review2) # Schedules agents
|
|
225
|
+
await flock.publish(review3) # Schedules agents
|
|
226
|
+
|
|
227
|
+
# Now trigger execution
|
|
228
|
+
await flock.run_until_idle() # All independent agents run in PARALLEL!
|
|
229
|
+
|
|
230
|
+
# Result: PARALLEL processing (~1x time if agents are independent)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Best Practices
|
|
234
|
+
|
|
235
|
+
**✅ DO: Batch when possible**
|
|
236
|
+
```python
|
|
237
|
+
# Good: Batch-publish customer reviews
|
|
238
|
+
for review in customer_reviews:
|
|
239
|
+
await flock.publish(review)
|
|
240
|
+
await flock.run_until_idle()
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**✅ DO: Use for multi-type workflows**
|
|
244
|
+
```python
|
|
245
|
+
# Good: Publish different types, let agents run in parallel
|
|
246
|
+
await flock.publish(XRayImage(...))
|
|
247
|
+
await flock.publish(LabResults(...))
|
|
248
|
+
await flock.publish(PatientHistory(...))
|
|
249
|
+
await flock.run_until_idle() # Radiologist, lab_tech, historian run concurrently
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**⚠️ CAREFUL: Separate workflows with traced_run()**
|
|
253
|
+
```python
|
|
254
|
+
# Better: Separate workflows explicitly
|
|
255
|
+
async with flock.traced_run("review_workflow"):
|
|
256
|
+
await flock.publish(review_workflow_input)
|
|
257
|
+
await flock.run_until_idle()
|
|
258
|
+
|
|
259
|
+
async with flock.traced_run("order_workflow"):
|
|
260
|
+
await flock.publish(order_workflow_input)
|
|
261
|
+
await flock.run_until_idle()
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Key Takeaway
|
|
265
|
+
|
|
266
|
+
The separation of `publish()` and `run_until_idle()` gives you **control over execution timing and batching**. This enables:
|
|
267
|
+
- ⚡ **Parallel execution** when agents are independent
|
|
268
|
+
- 🎛️ **Fine-grained control** over when execution happens
|
|
269
|
+
- 📊 **Better performance** for bulk operations
|
|
270
|
+
- 🔍 **Clearer workflow boundaries** with `traced_run()`
|
|
271
|
+
|
|
272
|
+
**This is not a bug or oversight - it's a fundamental design choice that enables patterns other frameworks can't easily support.**
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
### 🗄️ Persistent Blackboard History (SQLite Store)
|
|
277
|
+
|
|
278
|
+
**Production teams asked for auditability—now the blackboard can keep a full historical trail.**
|
|
279
|
+
|
|
280
|
+
#### Why this matters
|
|
281
|
+
- **Durable artifacts**: Everything on the blackboard (payloads, tags, visibility, correlation IDs) is stored on disk for replay, compliance, and debugging.
|
|
282
|
+
- **Faster postmortems**: Query `/api/v1/artifacts` with filters (`type`, `produced_by`, `tags`, `visibility`, time windows) to reconstruct agent cascades after the fact.
|
|
283
|
+
- **Operational dashboards**: The new **Historical Blackboard** module preloads persisted pages, exposes consumption metadata, and shows retention banners so operators know how far back they can scroll.
|
|
284
|
+
- **Retention policies**: CLI helpers make maintenance routine—`flock sqlite-maintenance my.db --delete-before 2025-01-01T00:00:00Z --vacuum` prunes old artifacts and compacts the store.
|
|
285
|
+
|
|
286
|
+
#### Quick start
|
|
287
|
+
```python
|
|
288
|
+
from flock import Flock
|
|
289
|
+
from flock.store import SQLiteBlackboardStore
|
|
290
|
+
|
|
291
|
+
store = SQLiteBlackboardStore(".flock/history.db")
|
|
292
|
+
await store.ensure_schema()
|
|
293
|
+
|
|
294
|
+
flock = Flock("openai/gpt-4.1", store=store)
|
|
295
|
+
await flock.publish(MyDreamPizza(pizza_idea="fermented garlic delight"))
|
|
296
|
+
await flock.run_until_idle()
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Kick the tyres with `examples/02-the-blackboard/01_persistent_pizza.py`, then launch `examples/03-the-dashboard/04_persistent_pizza_dashboard.py` to inspect the retained history alongside live WebSocket updates.
|
|
300
|
+
|
|
301
|
+
> **Heads-up:** The interface now returns `ArtifactEnvelope` objects when `embed_meta=True`. Future backends (Postgres, BigQuery, etc.) can implement the same contract to plug straight into the runtime and dashboard.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### 🔐 Context Providers - Smart Filtering & Security Boundaries
|
|
306
|
+
|
|
307
|
+
**Context Providers are the intelligent filter layer between agents and the blackboard—controlling what each agent sees, reducing token costs by 90%+, and automatically redacting sensitive data.**
|
|
308
|
+
|
|
309
|
+
**⚠️ IMPORTANT FOR AI AGENTS:** Context Providers implement the security architecture described in [docs/architecture.md](docs/architecture.md) and follow error handling patterns from [docs/patterns/error_handling.md](docs/patterns/error_handling.md). Read these documents to understand the design principles.
|
|
310
|
+
|
|
311
|
+
#### Why Context Providers Matter
|
|
312
|
+
|
|
313
|
+
**The Problem:**
|
|
314
|
+
- Agents seeing ALL artifacts wastes tokens (costs)
|
|
315
|
+
- No way to filter sensitive data before agents see it
|
|
316
|
+
- Performance degrades as blackboard grows
|
|
317
|
+
- Security vulnerabilities if agents bypass visibility
|
|
318
|
+
|
|
319
|
+
**The Solution:**
|
|
320
|
+
Context Providers enforce a security boundary that:
|
|
321
|
+
- ✅ **Reduces token costs** - Agents see only relevant artifacts (90%+ savings)
|
|
322
|
+
- ✅ **Protects sensitive data** - Auto-redact passwords, API keys, credit cards
|
|
323
|
+
- ✅ **Improves performance** - Less context = faster agent execution
|
|
324
|
+
- ✅ **Enforces security** - Agents cannot bypass provider filtering (architecturally impossible!)
|
|
325
|
+
|
|
326
|
+
**Understanding the Three-Layer Model:**
|
|
327
|
+
|
|
328
|
+
Flock uses three complementary filtering layers:
|
|
329
|
+
|
|
330
|
+
1. **Visibility** (security boundary) - Controls BOTH which agents trigger AND which artifacts they see in context
|
|
331
|
+
2. **Subscription Filters** (routing logic) - Controls WHEN agents trigger (e.g., `.consumes(Task, tags={"urgent"})`)
|
|
332
|
+
3. **Context Providers** (context shaping) - Controls WHAT agents see in their historical context
|
|
333
|
+
|
|
334
|
+
These layers work together to provide fine-grained control over agent execution and data access. Context Providers are the third layer—they filter what agents see in context but do NOT control triggering.
|
|
335
|
+
|
|
336
|
+
#### Quick Start: Global Filtering
|
|
337
|
+
|
|
338
|
+
**Filter all agents to see only urgent items:**
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
from flock import Flock
|
|
342
|
+
from flock.context_provider import FilteredContextProvider
|
|
343
|
+
from flock.store import FilterConfig
|
|
344
|
+
|
|
345
|
+
# Create provider that filters by tags
|
|
346
|
+
urgent_only = FilteredContextProvider(
|
|
347
|
+
FilterConfig(tags={"urgent", "high"}),
|
|
348
|
+
limit=50 # Max 50 artifacts
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
# Apply to ALL agents
|
|
352
|
+
flock = Flock("openai/gpt-4.1", context_provider=urgent_only)
|
|
353
|
+
|
|
354
|
+
# Publish with tags
|
|
355
|
+
await flock.publish(Task(...), tags={"urgent"}) # ✅ Agents see this
|
|
356
|
+
await flock.publish(Task(...), tags={"low"}) # ❌ Agents don't see this
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### Per-Agent Filtering (Role-Based)
|
|
360
|
+
|
|
361
|
+
**Different agents see different context:**
|
|
362
|
+
|
|
363
|
+
```python
|
|
364
|
+
# Global: Errors only
|
|
365
|
+
error_provider = FilteredContextProvider(FilterConfig(tags={"ERROR"}))
|
|
366
|
+
flock = Flock("openai/gpt-4.1", context_provider=error_provider)
|
|
367
|
+
|
|
368
|
+
# Junior engineer: Errors only (uses global)
|
|
369
|
+
junior = flock.agent("junior").consumes(LogEntry).publishes(Report).agent
|
|
370
|
+
|
|
371
|
+
# Senior engineer: Errors + Warnings (override global)
|
|
372
|
+
warn_provider = FilteredContextProvider(FilterConfig(tags={"ERROR", "WARN"}))
|
|
373
|
+
senior = flock.agent("senior").consumes(LogEntry).publishes(Analysis).agent
|
|
374
|
+
senior.context_provider = warn_provider # 🎯 Per-agent override!
|
|
375
|
+
|
|
376
|
+
# Platform team: Everything (override global)
|
|
377
|
+
all_provider = FilteredContextProvider(FilterConfig(tags={"DEBUG", "INFO", "WARN", "ERROR"}))
|
|
378
|
+
platform = flock.agent("platform").consumes(LogEntry).publishes(Report).agent
|
|
379
|
+
platform.context_provider = all_provider
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Provider Priority:**
|
|
383
|
+
```
|
|
384
|
+
Per-Agent Provider > Global Provider > DefaultContextProvider
|
|
385
|
+
(highest) (medium) (fallback)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### Production-Ready: Password Redaction
|
|
389
|
+
|
|
390
|
+
**Automatically redact sensitive data from agent context:**
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
from examples.context_provider import PasswordRedactorProvider
|
|
394
|
+
|
|
395
|
+
# Create provider with built-in patterns
|
|
396
|
+
provider = PasswordRedactorProvider(
|
|
397
|
+
redaction_text="[REDACTED]",
|
|
398
|
+
redact_emails=True,
|
|
399
|
+
log_redactions=True # Audit trail
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
flock = Flock("openai/gpt-4.1", context_provider=provider)
|
|
403
|
+
|
|
404
|
+
# Publish data with secrets
|
|
405
|
+
await flock.publish(UserData(
|
|
406
|
+
password="MySecret123", # → [REDACTED]
|
|
407
|
+
api_key="sk-1234567890abcdef", # → [REDACTED]
|
|
408
|
+
email="user@example.com" # → [REDACTED]
|
|
409
|
+
))
|
|
410
|
+
|
|
411
|
+
# Agents see redacted version automatically!
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**What gets redacted:**
|
|
415
|
+
- 🔒 Passwords and secrets
|
|
416
|
+
- 🔑 API keys (OpenAI, AWS, GitHub, GitLab, Stripe, Google)
|
|
417
|
+
- 🎫 Bearer tokens and JWT
|
|
418
|
+
- 💳 Credit card numbers (Visa, MC, Amex, Discover)
|
|
419
|
+
- 🆔 Social Security Numbers
|
|
420
|
+
- 🔐 Private keys (RSA, EC, OpenSSH)
|
|
421
|
+
- 📧 Email addresses (optional)
|
|
422
|
+
|
|
423
|
+
#### FilterConfig API Reference
|
|
424
|
+
|
|
425
|
+
**Declarative filtering with multiple criteria:**
|
|
426
|
+
|
|
427
|
+
```python
|
|
428
|
+
from flock.store import FilterConfig
|
|
429
|
+
|
|
430
|
+
# Combine multiple filters (AND logic)
|
|
431
|
+
config = FilterConfig(
|
|
432
|
+
tags={"ERROR", "CRITICAL"}, # OR logic: any of these tags
|
|
433
|
+
type_names={"SystemEvent", "Alert"}, # OR logic: any of these types
|
|
434
|
+
produced_by=["monitor", "watchdog"], # OR logic: from any of these agents
|
|
435
|
+
correlation_id="incident-123" # Exact match
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
provider = FilteredContextProvider(config, limit=100)
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Criteria are combined with AND logic:**
|
|
442
|
+
- Must have (ERROR OR CRITICAL) tag
|
|
443
|
+
- AND must be (SystemEvent OR Alert) type
|
|
444
|
+
- AND must be from (monitor OR watchdog) agent
|
|
445
|
+
- AND must have correlation_id "incident-123"
|
|
446
|
+
|
|
447
|
+
#### Custom Context Providers
|
|
448
|
+
|
|
449
|
+
**Build your own filtering logic:**
|
|
450
|
+
|
|
451
|
+
```python
|
|
452
|
+
from flock.context_provider import BaseContextProvider, ContextRequest
|
|
453
|
+
from flock.artifacts import Artifact
|
|
454
|
+
|
|
455
|
+
class TimeBoundProvider(BaseContextProvider):
|
|
456
|
+
"""Only show artifacts from last 1 hour.
|
|
457
|
+
|
|
458
|
+
Security is enforced automatically by BaseContextProvider!
|
|
459
|
+
"""
|
|
460
|
+
|
|
461
|
+
async def get_artifacts(self, request: ContextRequest) -> list[Artifact]:
|
|
462
|
+
cutoff = datetime.now() - timedelta(hours=1)
|
|
463
|
+
|
|
464
|
+
# Query all artifacts
|
|
465
|
+
artifacts, _ = await request.store.query_artifacts(limit=1000)
|
|
466
|
+
|
|
467
|
+
# Apply time-based filtering
|
|
468
|
+
recent = [a for a in artifacts if a.created_at >= cutoff]
|
|
469
|
+
|
|
470
|
+
return recent
|
|
471
|
+
|
|
472
|
+
# ✨ BaseContextProvider automatically:
|
|
473
|
+
# - Filters by visibility (MANDATORY, cannot bypass!)
|
|
474
|
+
# - Excludes requested IDs
|
|
475
|
+
# - Serializes to standard format
|
|
476
|
+
|
|
477
|
+
# Usage
|
|
478
|
+
provider = TimeBoundProvider()
|
|
479
|
+
flock = Flock("openai/gpt-4.1", context_provider=provider)
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**Why this is better:**
|
|
483
|
+
- ✅ **75% less code** - 5 lines vs 20+ lines
|
|
484
|
+
- ✅ **Impossible to bypass security** - visibility enforced by base class
|
|
485
|
+
- ✅ **Consistent serialization** - automatic standard format
|
|
486
|
+
- ✅ **Focus on business logic** - not infrastructure
|
|
487
|
+
|
|
488
|
+
#### Real-World Use Cases
|
|
489
|
+
|
|
490
|
+
**Healthcare (HIPAA Compliance):**
|
|
491
|
+
```python
|
|
492
|
+
# Redact PHI (Protected Health Information)
|
|
493
|
+
from examples.context_provider import PasswordRedactorProvider
|
|
494
|
+
|
|
495
|
+
phi_provider = PasswordRedactorProvider(
|
|
496
|
+
custom_patterns={
|
|
497
|
+
"ssn": r"\b\d{3}-\d{2}-\d{4}\b",
|
|
498
|
+
"mrn": r"MRN[:\s]*\d{6,10}",
|
|
499
|
+
"dob": r"\b\d{2}/\d{2}/\d{4}\b",
|
|
500
|
+
}
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
flock = Flock("openai/gpt-4.1", context_provider=phi_provider)
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
**DevOps (Log Filtering):**
|
|
507
|
+
```python
|
|
508
|
+
# Error engineers see only errors
|
|
509
|
+
error_provider = FilteredContextProvider(FilterConfig(tags={"ERROR", "CRITICAL"}))
|
|
510
|
+
error_agent.context_provider = error_provider
|
|
511
|
+
|
|
512
|
+
# Platform team sees everything
|
|
513
|
+
all_provider = FilteredContextProvider(FilterConfig(tags={"DEBUG", "INFO", "WARN", "ERROR"}))
|
|
514
|
+
platform_agent.context_provider = all_provider
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
**Multi-Tenant SaaS (Customer Isolation):**
|
|
518
|
+
```python
|
|
519
|
+
# Each tenant gets isolated context
|
|
520
|
+
tenant_a_provider = FilteredContextProvider(FilterConfig(correlation_id=f"tenant_{customer_a.id}"))
|
|
521
|
+
tenant_a_agent.context_provider = tenant_a_provider
|
|
522
|
+
|
|
523
|
+
tenant_b_provider = FilteredContextProvider(FilterConfig(correlation_id=f"tenant_{customer_b.id}"))
|
|
524
|
+
tenant_b_agent.context_provider = tenant_b_provider
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
#### Performance Impact
|
|
528
|
+
|
|
529
|
+
**Token Cost Reduction:**
|
|
530
|
+
|
|
531
|
+
```python
|
|
532
|
+
# ❌ Before (no filtering): Agent sees 1000 artifacts = 200,000 tokens
|
|
533
|
+
# Cost: $0.006 per agent call
|
|
534
|
+
|
|
535
|
+
# ✅ After (smart filtering): Agent sees 10 relevant artifacts = 2,000 tokens
|
|
536
|
+
# Cost: $0.00006 per agent call
|
|
537
|
+
|
|
538
|
+
# 💰 99% cost reduction!
|
|
539
|
+
|
|
540
|
+
provider = FilteredContextProvider(FilterConfig(tags={"urgent"}), limit=10)
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
#### Security Best Practices
|
|
544
|
+
|
|
545
|
+
**✅ DO:**
|
|
546
|
+
- Always enforce visibility (NEVER skip)
|
|
547
|
+
- Use `FilteredContextProvider` for common patterns
|
|
548
|
+
- Test redaction patterns with real data
|
|
549
|
+
- Log security events for audit trails
|
|
550
|
+
- Limit by default (start restrictive)
|
|
551
|
+
|
|
552
|
+
**❌ DON'T:**
|
|
553
|
+
- Don't skip visibility filtering (security boundary!)
|
|
554
|
+
- Don't leak sensitive data in nested objects
|
|
555
|
+
- Don't cache redacted data without re-applying redaction
|
|
556
|
+
- Don't trust agent input (agents are untrusted)
|
|
557
|
+
- Don't expose infrastructure details
|
|
558
|
+
|
|
559
|
+
#### Learn More
|
|
560
|
+
|
|
561
|
+
**📚 Complete Guide:** [docs/guides/context-providers.md](docs/guides/context-providers.md) - Architecture, security model, advanced patterns
|
|
562
|
+
|
|
563
|
+
**💡 Examples:** [examples/08-context-provider/](examples/08-context-provider/) - 5 progressive examples from beginner to expert
|
|
564
|
+
|
|
565
|
+
**🎁 Production Code:** [examples/08-context-provider/05_password_redactor.py](examples/08-context-provider/05_password_redactor.py) - Copy-paste ready password filtering
|
|
566
|
+
|
|
567
|
+
#### Quick Reference
|
|
568
|
+
|
|
569
|
+
```python
|
|
570
|
+
# Global filtering
|
|
571
|
+
flock = Flock("openai/gpt-4.1", context_provider=FilteredContextProvider(FilterConfig(tags={"urgent"})))
|
|
572
|
+
|
|
573
|
+
# Per-agent override
|
|
574
|
+
agent.context_provider = FilteredContextProvider(FilterConfig(tags={"ERROR", "WARN"}))
|
|
575
|
+
|
|
576
|
+
# Password redaction
|
|
577
|
+
from examples.context_provider import PasswordRedactorProvider
|
|
578
|
+
flock = Flock("openai/gpt-4.1", context_provider=PasswordRedactorProvider())
|
|
579
|
+
|
|
580
|
+
# Custom provider
|
|
581
|
+
class MyProvider(ContextProvider):
|
|
582
|
+
async def __call__(self, request: ContextRequest) -> list[dict[str, Any]]:
|
|
583
|
+
# Query + filter by visibility (MANDATORY) + your logic
|
|
584
|
+
pass
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
### 🔒 Test Isolation and Mock Cleanup - The Contamination Trap
|
|
590
|
+
|
|
591
|
+
**We fixed 32 failing tests caused by test contamination - here's what we learned:**
|
|
592
|
+
|
|
593
|
+
#### The Problem
|
|
594
|
+
Tests were modifying class-level properties with PropertyMock that persisted across test boundaries:
|
|
595
|
+
|
|
596
|
+
```python
|
|
597
|
+
# ❌ WRONG: Contaminates other tests
|
|
598
|
+
def test_something(orchestrator):
|
|
599
|
+
type(orchestrator).agents = PropertyMock(return_value=[mock_agent])
|
|
600
|
+
# No cleanup - mock persists!
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
#### The Solution
|
|
604
|
+
Always use fixture cleanup with yield pattern:
|
|
605
|
+
|
|
606
|
+
```python
|
|
607
|
+
# ✅ CORRECT: Proper cleanup
|
|
608
|
+
@pytest.fixture
|
|
609
|
+
def dashboard_service_with_mocks(orchestrator):
|
|
610
|
+
original_agents = getattr(type(orchestrator), "agents", None)
|
|
611
|
+
type(orchestrator).agents = PropertyMock(return_value=[mock_agent])
|
|
612
|
+
try:
|
|
613
|
+
yield service
|
|
614
|
+
finally:
|
|
615
|
+
# Restore original or delete if it didn't exist
|
|
616
|
+
if original_agents is not None:
|
|
617
|
+
type(orchestrator).agents = original_agents
|
|
618
|
+
elif hasattr(type(orchestrator), "agents"):
|
|
619
|
+
delattr(type(orchestrator), "agents")
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
#### Best Practices for Test Isolation
|
|
623
|
+
|
|
624
|
+
1. **Create Helper Functions for Complex Mocks**
|
|
625
|
+
2. **Use Fixture Cleanup Pattern** (store original, try/finally, restore)
|
|
626
|
+
3. **Test in Isolation First** (run files individually to check contamination)
|
|
627
|
+
4. **Common Contamination Sources**: PropertyMock on class attributes, module-level patches, shared mutable state, async event loops, Rich/logging state pollution
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
### 📦 Version Bumping - Don't Break PyPI Releases!
|
|
632
|
+
|
|
633
|
+
**⚠️ CRITICAL FOR ALL CODE CHANGES:** Always increment version numbers when making changes that will be committed and pushed. Forgetting this breaks the PyPI publishing workflow!
|
|
634
|
+
|
|
635
|
+
#### Why This Matters
|
|
636
|
+
|
|
637
|
+
The automated PyPI release pipeline checks if the version in `pyproject.toml` has been incremented. If you push code changes without bumping the version:
|
|
638
|
+
- ❌ PyPI publish workflow fails
|
|
639
|
+
- ❌ Users can't get your fixes/features via `pip install`
|
|
640
|
+
- ❌ Other developers get confused about which version has which features
|
|
641
|
+
|
|
642
|
+
#### What to Bump
|
|
643
|
+
|
|
644
|
+
**Backend version (REQUIRED for backend code changes):**
|
|
645
|
+
```toml
|
|
646
|
+
# pyproject.toml
|
|
647
|
+
[project]
|
|
648
|
+
version = "0.5.0b56" # Increment this! e.g., "0.5.0b57"
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
**Frontend version (REQUIRED for dashboard/UI changes):**
|
|
652
|
+
```json
|
|
653
|
+
// src/flock/frontend/package.json
|
|
654
|
+
{
|
|
655
|
+
"version": "0.1.2" // Increment this! e.g., "0.1.3"
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
#### When to Bump
|
|
660
|
+
|
|
661
|
+
**✅ ALWAYS bump backend version for:**
|
|
662
|
+
- Any Python code changes in `src/flock/`
|
|
663
|
+
- Bug fixes, features, refactors
|
|
664
|
+
- Commits that modify backend behavior
|
|
665
|
+
|
|
666
|
+
Docs-only changes (in `docs/`, `README.md`) do not require a version bump.
|
|
667
|
+
|
|
668
|
+
**✅ ALWAYS bump frontend version for:**
|
|
669
|
+
- Dashboard UI changes
|
|
670
|
+
- React/TypeScript component updates
|
|
671
|
+
- CSS/styling changes
|
|
672
|
+
- Any changes in `src/flock/frontend/`
|
|
673
|
+
|
|
674
|
+
#### Versioning Pattern
|
|
675
|
+
|
|
676
|
+
We use **semantic versioning with beta tags**:
|
|
677
|
+
- `0.5.0b56` → `0.5.0b57` for regular changes (increment beta number)
|
|
678
|
+
- `0.1.2` → `0.1.3` for frontend changes (increment patch)
|
|
679
|
+
|
|
680
|
+
#### How to Bump
|
|
681
|
+
|
|
682
|
+
```bash
|
|
683
|
+
# 1. Make your code changes
|
|
684
|
+
# 2. Bump versions BEFORE committing
|
|
685
|
+
# Edit pyproject.toml: version = "0.5.0b57"
|
|
686
|
+
# Edit package.json: "version": "0.1.3"
|
|
687
|
+
|
|
688
|
+
# 3. Commit version bumps with your changes OR as separate commit
|
|
689
|
+
git add pyproject.toml src/flock/frontend/package.json
|
|
690
|
+
git commit -m "chore: bump version to 0.5.0b57"
|
|
691
|
+
|
|
692
|
+
# 4. Push (pre-commit hook will verify versions were bumped)
|
|
693
|
+
git push
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
#### Pre-commit Hook Protection
|
|
697
|
+
|
|
698
|
+
The repository has a pre-commit hook that **checks if versions were bumped**. If you forget, it will warn you:
|
|
699
|
+
|
|
700
|
+
```bash
|
|
701
|
+
check if version bump needed.............................................Failed
|
|
702
|
+
- hook id: version-check
|
|
703
|
+
|
|
704
|
+
❌ No version changes detected in modified Python/frontend files
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
#### Quick Checklist for PRs
|
|
708
|
+
|
|
709
|
+
Before creating a PR, verify:
|
|
710
|
+
- [ ] Backend version bumped in `pyproject.toml` (if any Python changes)
|
|
711
|
+
- [ ] Frontend version bumped in `package.json` (if any UI changes)
|
|
712
|
+
- [ ] Version bump committed (separate commit is fine)
|
|
713
|
+
- [ ] Pre-commit hooks pass
|
|
714
|
+
- [ ] **PR targets `main` branch** ✅
|
|
715
|
+
|
|
716
|
+
#### ⚠️ CRITICAL: PR Base Branch
|
|
717
|
+
|
|
718
|
+
**ALL pull requests MUST target the `main` branch!**
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
# ✅ CORRECT: PR into main branch
|
|
722
|
+
gh pr create --base main --title "..." --body "..."
|
|
723
|
+
|
|
724
|
+
# ❌ WRONG: PR into other branches without discussion
|
|
725
|
+
gh pr create --base some-other-branch --title "..." --body "..."
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
**Why this matters:**
|
|
729
|
+
- The `main` branch is the active development branch
|
|
730
|
+
- All features should be validated through PR review before merging
|
|
731
|
+
- Keeps the project history clean and linear
|
|
732
|
+
|
|
733
|
+
**If you accidentally create a PR against the wrong branch:**
|
|
734
|
+
1. Close the incorrect PR: `gh pr close <number>`
|
|
735
|
+
2. Recreate against `main`: `gh pr create --base main ...`
|
|
736
|
+
|
|
737
|
+
**Remember: It's better to increment versions too often than too rarely. Each meaningful change should get a version bump!**
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
## 🔍 Observability & Debugging with OpenTelemetry + DuckDB
|
|
742
|
+
|
|
743
|
+
Flock includes **production-grade distributed tracing** that captures every operation with full input/output data—enabling both human and AI-assisted debugging.
|
|
744
|
+
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
## 🤖 FOR AI AGENTS: Tracing is Your PRIMARY Debugging Tool
|
|
748
|
+
|
|
749
|
+
**⚠️ CRITICAL FOR AI AGENTS:** When debugging or testing Flock applications, **ALWAYS start with tracing**. The trace database contains the complete execution history with full input/output capture—this is your source of truth.
|
|
750
|
+
|
|
751
|
+
### Why Tracing First?
|
|
752
|
+
|
|
753
|
+
**Traditional debugging (logs, print statements):**
|
|
754
|
+
- ❌ Requires code changes
|
|
755
|
+
- ❌ Missing context (what happened before/after)
|
|
756
|
+
- ❌ No timing information
|
|
757
|
+
- ❌ Incomplete input/output data
|
|
758
|
+
|
|
759
|
+
**Tracing-first debugging:**
|
|
760
|
+
- ✅ **Zero code changes** - just query the database
|
|
761
|
+
- ✅ **Complete execution history** - every operation captured
|
|
762
|
+
- ✅ **Full I/O data** - exact inputs that caused issues
|
|
763
|
+
- ✅ **Timing analysis** - identify bottlenecks instantly
|
|
764
|
+
- ✅ **Parent-child relationships** - understand call hierarchy
|
|
765
|
+
- ✅ **Correlation IDs** - track requests across agents
|
|
766
|
+
|
|
767
|
+
### AI Agent Debugging Workflow (Step-by-Step)
|
|
768
|
+
|
|
769
|
+
**When a user reports an issue or asks you to debug/test:**
|
|
770
|
+
|
|
771
|
+
#### Step 1: Enable Tracing (if not already enabled)
|
|
772
|
+
```bash
|
|
773
|
+
# Check if tracing is enabled
|
|
774
|
+
cat .env | grep FLOCK_AUTO_TRACE
|
|
775
|
+
|
|
776
|
+
# If not enabled, add to .env:
|
|
777
|
+
FLOCK_AUTO_TRACE=true
|
|
778
|
+
FLOCK_TRACE_FILE=true
|
|
779
|
+
|
|
780
|
+
# Or export temporarily:
|
|
781
|
+
export FLOCK_AUTO_TRACE=true FLOCK_TRACE_FILE=true
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
#### Step 2: Run the Code to Capture Trace
|
|
785
|
+
```bash
|
|
786
|
+
# Run the problematic script/test
|
|
787
|
+
uv run python examples/path/to/script.py
|
|
788
|
+
|
|
789
|
+
# Or run specific test
|
|
790
|
+
uv run pytest tests/test_file.py::test_name -v
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
#### Step 3: Query Trace Database for Overview
|
|
794
|
+
```python
|
|
795
|
+
import duckdb
|
|
796
|
+
|
|
797
|
+
conn = duckdb.connect('.flock/traces.duckdb', read_only=True)
|
|
798
|
+
|
|
799
|
+
# Get recent traces
|
|
800
|
+
traces = conn.execute("""
|
|
801
|
+
SELECT
|
|
802
|
+
trace_id,
|
|
803
|
+
COUNT(*) as span_count,
|
|
804
|
+
MIN(start_time) as trace_start,
|
|
805
|
+
(MAX(end_time) - MIN(start_time)) / 1000000.0 as total_duration_ms,
|
|
806
|
+
SUM(CASE WHEN status_code = 'ERROR' THEN 1 ELSE 0 END) as error_count
|
|
807
|
+
FROM spans
|
|
808
|
+
GROUP BY trace_id
|
|
809
|
+
ORDER BY trace_start DESC
|
|
810
|
+
LIMIT 10
|
|
811
|
+
""").fetchall()
|
|
812
|
+
|
|
813
|
+
for trace in traces:
|
|
814
|
+
print(f"Trace: {trace[0][:16]}... | Spans: {trace[1]} | Duration: {trace[3]:.2f}ms | Errors: {trace[4]}")
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
#### Step 4: Analyze Specific Trace
|
|
818
|
+
```python
|
|
819
|
+
# Get the most recent trace (or the one with errors)
|
|
820
|
+
latest_trace_id = traces[0][0]
|
|
821
|
+
|
|
822
|
+
# Get execution flow with hierarchy
|
|
823
|
+
flow = conn.execute("""
|
|
824
|
+
SELECT
|
|
825
|
+
span_id,
|
|
826
|
+
parent_id,
|
|
827
|
+
name,
|
|
828
|
+
service,
|
|
829
|
+
duration_ms,
|
|
830
|
+
status_code,
|
|
831
|
+
status_description,
|
|
832
|
+
json_extract(attributes, '$.correlation_id') as correlation_id
|
|
833
|
+
FROM spans
|
|
834
|
+
WHERE trace_id = ?
|
|
835
|
+
ORDER BY start_time ASC
|
|
836
|
+
""", [latest_trace_id]).fetchall()
|
|
837
|
+
|
|
838
|
+
# Print hierarchical execution
|
|
839
|
+
for span in flow:
|
|
840
|
+
indent = ' ' if span[1] else '' # Indent children
|
|
841
|
+
status_icon = '✅' if span[5] == 'OK' else '❌'
|
|
842
|
+
print(f"{status_icon} {indent}{span[2]} ({span[3]}) - {span[4]:.2f}ms")
|
|
843
|
+
if span[6]: # Error description
|
|
844
|
+
print(f" ERROR: {span[6]}")
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
#### Step 5: Examine Input/Output Data
|
|
848
|
+
```python
|
|
849
|
+
# Get input that caused an error
|
|
850
|
+
error_details = conn.execute("""
|
|
851
|
+
SELECT
|
|
852
|
+
name,
|
|
853
|
+
status_description,
|
|
854
|
+
json_extract(attributes, '$.input.artifacts') as input_artifacts,
|
|
855
|
+
json_extract(attributes, '$.output.value') as output_value,
|
|
856
|
+
attributes
|
|
857
|
+
FROM spans
|
|
858
|
+
WHERE trace_id = ?
|
|
859
|
+
AND status_code = 'ERROR'
|
|
860
|
+
""", [latest_trace_id]).fetchall()
|
|
861
|
+
|
|
862
|
+
# Inspect the exact input that caused failure
|
|
863
|
+
import json
|
|
864
|
+
for error in error_details:
|
|
865
|
+
print(f"\n❌ ERROR in {error[0]}")
|
|
866
|
+
print(f"Message: {error[1]}")
|
|
867
|
+
print(f"Input: {error[2]}")
|
|
868
|
+
print(f"Output: {error[3]}")
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
#### Step 6: Identify Root Cause
|
|
872
|
+
```python
|
|
873
|
+
# Common root cause queries:
|
|
874
|
+
|
|
875
|
+
# 1. Find the slowest operation in the trace
|
|
876
|
+
slowest = conn.execute("""
|
|
877
|
+
SELECT name, service, duration_ms
|
|
878
|
+
FROM spans
|
|
879
|
+
WHERE trace_id = ?
|
|
880
|
+
ORDER BY duration_ms DESC
|
|
881
|
+
LIMIT 1
|
|
882
|
+
""", [latest_trace_id]).fetchone()
|
|
883
|
+
print(f"Bottleneck: {slowest[0]} ({slowest[1]}) took {slowest[2]:.2f}ms")
|
|
884
|
+
|
|
885
|
+
# 2. Check if agent was triggered correctly
|
|
886
|
+
agent_triggers = conn.execute("""
|
|
887
|
+
SELECT
|
|
888
|
+
name,
|
|
889
|
+
json_extract(attributes, '$.input.artifacts') as consumed_artifacts
|
|
890
|
+
FROM spans
|
|
891
|
+
WHERE trace_id = ?
|
|
892
|
+
AND name LIKE 'Agent.execute'
|
|
893
|
+
""", [latest_trace_id]).fetchall()
|
|
894
|
+
|
|
895
|
+
# 3. Verify artifact types produced
|
|
896
|
+
artifacts_produced = conn.execute("""
|
|
897
|
+
SELECT DISTINCT
|
|
898
|
+
service as agent,
|
|
899
|
+
json_extract(attributes, '$.output.type') as artifact_type
|
|
900
|
+
FROM spans
|
|
901
|
+
WHERE trace_id = ?
|
|
902
|
+
AND attributes->>'output.type' IS NOT NULL
|
|
903
|
+
""", [latest_trace_id]).fetchall()
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
#### Step 7: Report Findings & Fix
|
|
907
|
+
```python
|
|
908
|
+
# Close connection
|
|
909
|
+
conn.close()
|
|
910
|
+
|
|
911
|
+
# Now you have:
|
|
912
|
+
# - Exact execution flow
|
|
913
|
+
# - Input data that caused the issue
|
|
914
|
+
# - Timing information (bottlenecks)
|
|
915
|
+
# - Error messages and stack traces
|
|
916
|
+
# - Artifact flow between agents
|
|
917
|
+
|
|
918
|
+
# Report to user with specific findings
|
|
919
|
+
print("""
|
|
920
|
+
DIAGNOSIS COMPLETE:
|
|
921
|
+
|
|
922
|
+
Issue: <describe the problem>
|
|
923
|
+
Root Cause: <specific operation/input that failed>
|
|
924
|
+
Evidence:
|
|
925
|
+
- Trace ID: {trace_id}
|
|
926
|
+
- Failed at: {operation_name}
|
|
927
|
+
- Input: {input_data}
|
|
928
|
+
- Duration: {duration}ms
|
|
929
|
+
|
|
930
|
+
Recommendation: <how to fix>
|
|
931
|
+
""")
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
### Essential Queries for AI Agents
|
|
935
|
+
|
|
936
|
+
**Keep these queries ready for common debugging tasks:**
|
|
937
|
+
|
|
938
|
+
#### 1. Find Most Recent Workflow Execution
|
|
939
|
+
```python
|
|
940
|
+
latest_workflow = conn.execute("""
|
|
941
|
+
SELECT trace_id,
|
|
942
|
+
COUNT(*) as operations,
|
|
943
|
+
(MAX(end_time) - MIN(start_time)) / 1000000.0 as duration_ms
|
|
944
|
+
FROM spans
|
|
945
|
+
GROUP BY trace_id
|
|
946
|
+
ORDER BY MIN(start_time) DESC
|
|
947
|
+
LIMIT 1
|
|
948
|
+
""").fetchone()
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
#### 2. Check Agent Lifecycle Execution
|
|
952
|
+
```python
|
|
953
|
+
# Verify all lifecycle hooks fired correctly
|
|
954
|
+
lifecycle = conn.execute("""
|
|
955
|
+
SELECT name, duration_ms, status_code
|
|
956
|
+
FROM spans
|
|
957
|
+
WHERE trace_id = ?
|
|
958
|
+
AND service LIKE '%Component'
|
|
959
|
+
OR service LIKE '%Engine'
|
|
960
|
+
ORDER BY start_time ASC
|
|
961
|
+
""", [trace_id]).fetchall()
|
|
962
|
+
|
|
963
|
+
# Expected order: on_initialize → on_pre_consume → on_pre_evaluate →
|
|
964
|
+
# evaluate → on_post_evaluate → on_post_publish → on_terminate
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
#### 3. Validate Artifact Flow
|
|
968
|
+
```python
|
|
969
|
+
# Track artifact transformations
|
|
970
|
+
artifact_flow = conn.execute("""
|
|
971
|
+
SELECT
|
|
972
|
+
name,
|
|
973
|
+
service,
|
|
974
|
+
json_extract(attributes, '$.input.artifacts[0].type') as input_type,
|
|
975
|
+
json_extract(attributes, '$.output.type') as output_type
|
|
976
|
+
FROM spans
|
|
977
|
+
WHERE trace_id = ?
|
|
978
|
+
AND (attributes->>'input.artifacts' IS NOT NULL
|
|
979
|
+
OR attributes->>'output.type' IS NOT NULL)
|
|
980
|
+
ORDER BY start_time ASC
|
|
981
|
+
""", [trace_id]).fetchall()
|
|
982
|
+
|
|
983
|
+
# Verify expected transformations: InputType → Agent → OutputType
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
#### 4. Detect Performance Issues
|
|
987
|
+
```python
|
|
988
|
+
# Find operations that took >1 second
|
|
989
|
+
slow_ops = conn.execute("""
|
|
990
|
+
SELECT
|
|
991
|
+
name,
|
|
992
|
+
service,
|
|
993
|
+
duration_ms,
|
|
994
|
+
json_extract(attributes, '$.input.artifacts[0].payload') as input_payload
|
|
995
|
+
FROM spans
|
|
996
|
+
WHERE trace_id = ?
|
|
997
|
+
AND duration_ms > 1000
|
|
998
|
+
ORDER BY duration_ms DESC
|
|
999
|
+
""", [trace_id]).fetchall()
|
|
1000
|
+
|
|
1001
|
+
# Check if large payloads are causing slowness
|
|
1002
|
+
for op in slow_ops:
|
|
1003
|
+
if op[3]:
|
|
1004
|
+
payload_size = len(str(op[3]))
|
|
1005
|
+
print(f"{op[0]}: {op[2]:.0f}ms (payload: {payload_size} bytes)")
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
#### 5. Debug Test Failures
|
|
1009
|
+
```python
|
|
1010
|
+
# When a test fails, find what actually happened vs expected
|
|
1011
|
+
test_execution = conn.execute("""
|
|
1012
|
+
SELECT
|
|
1013
|
+
name,
|
|
1014
|
+
status_code,
|
|
1015
|
+
status_description,
|
|
1016
|
+
json_extract(attributes, '$.input.artifacts') as input,
|
|
1017
|
+
json_extract(attributes, '$.output.value') as output
|
|
1018
|
+
FROM spans
|
|
1019
|
+
WHERE trace_id = ?
|
|
1020
|
+
ORDER BY start_time ASC
|
|
1021
|
+
""", [trace_id]).fetchall()
|
|
1022
|
+
|
|
1023
|
+
# Compare actual output with test expectations
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
### Common Debugging Scenarios for AI Agents
|
|
1027
|
+
|
|
1028
|
+
#### Scenario A: "Test is failing but I don't know why"
|
|
1029
|
+
```bash
|
|
1030
|
+
# Step 1: Run test with tracing
|
|
1031
|
+
FLOCK_AUTO_TRACE=true FLOCK_TRACE_FILE=true uv run pytest tests/test_file.py::test_name -v
|
|
1032
|
+
|
|
1033
|
+
# Step 2: Query for test execution
|
|
1034
|
+
uv run python -c "
|
|
1035
|
+
import duckdb
|
|
1036
|
+
conn = duckdb.connect('.flock/traces.duckdb', read_only=True)
|
|
1037
|
+
|
|
1038
|
+
# Find most recent trace
|
|
1039
|
+
trace = conn.execute('''
|
|
1040
|
+
SELECT trace_id FROM spans
|
|
1041
|
+
GROUP BY trace_id
|
|
1042
|
+
ORDER BY MIN(start_time) DESC LIMIT 1
|
|
1043
|
+
''').fetchone()[0]
|
|
1044
|
+
|
|
1045
|
+
# Get all operations
|
|
1046
|
+
ops = conn.execute('''
|
|
1047
|
+
SELECT name, status_code, duration_ms
|
|
1048
|
+
FROM spans WHERE trace_id = ?
|
|
1049
|
+
ORDER BY start_time
|
|
1050
|
+
''', [trace]).fetchall()
|
|
1051
|
+
|
|
1052
|
+
for op in ops:
|
|
1053
|
+
status = '✅' if op[1] == 'OK' else '❌'
|
|
1054
|
+
print(f'{status} {op[0]}: {op[2]:.2f}ms')
|
|
1055
|
+
"
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
#### Scenario B: "Agent not producing expected output"
|
|
1059
|
+
```python
|
|
1060
|
+
import duckdb
|
|
1061
|
+
conn = duckdb.connect('.flock/traces.duckdb', read_only=True)
|
|
1062
|
+
|
|
1063
|
+
# Find what the agent actually produced
|
|
1064
|
+
trace_id = '<latest_trace_id>'
|
|
1065
|
+
output = conn.execute("""
|
|
1066
|
+
SELECT
|
|
1067
|
+
service as agent_name,
|
|
1068
|
+
json_extract(attributes, '$.output.type') as output_type,
|
|
1069
|
+
json_extract(attributes, '$.output.value') as output_value
|
|
1070
|
+
FROM spans
|
|
1071
|
+
WHERE trace_id = ?
|
|
1072
|
+
AND name = 'Agent.execute'
|
|
1073
|
+
""", [trace_id]).fetchone()
|
|
1074
|
+
|
|
1075
|
+
print(f"Agent: {output[0]}")
|
|
1076
|
+
print(f"Output Type: {output[1]}")
|
|
1077
|
+
print(f"Output Value: {output[2]}")
|
|
1078
|
+
|
|
1079
|
+
# Compare with expected output type in test
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
#### Scenario C: "Agent not being triggered"
|
|
1083
|
+
```python
|
|
1084
|
+
# Check if artifact was published and if agent subscribed
|
|
1085
|
+
trace_id = '<latest_trace_id>'
|
|
1086
|
+
|
|
1087
|
+
published = conn.execute("""
|
|
1088
|
+
SELECT json_extract(attributes, '$.output.type') as artifact_type
|
|
1089
|
+
FROM spans
|
|
1090
|
+
WHERE trace_id = ?
|
|
1091
|
+
AND name = 'Flock.publish'
|
|
1092
|
+
""", [trace_id]).fetchone()
|
|
1093
|
+
|
|
1094
|
+
print(f"Published artifact type: {published[0]}")
|
|
1095
|
+
|
|
1096
|
+
# Check if any agent consumed it
|
|
1097
|
+
consumers = conn.execute("""
|
|
1098
|
+
SELECT service, json_extract(attributes, '$.input.artifacts[0].type') as consumed_type
|
|
1099
|
+
FROM spans
|
|
1100
|
+
WHERE trace_id = ?
|
|
1101
|
+
AND name = 'Agent.execute'
|
|
1102
|
+
""", [trace_id]).fetchall()
|
|
1103
|
+
|
|
1104
|
+
if not consumers:
|
|
1105
|
+
print("❌ No agents consumed this artifact!")
|
|
1106
|
+
print("Check agent subscription rules (consumes clause)")
|
|
1107
|
+
else:
|
|
1108
|
+
for consumer in consumers:
|
|
1109
|
+
print(f"✅ {consumer[0]} consumed {consumer[1]}")
|
|
1110
|
+
```
|
|
1111
|
+
|
|
1112
|
+
#### Scenario D: "Performance regression"
|
|
1113
|
+
```python
|
|
1114
|
+
# Compare execution times across traces
|
|
1115
|
+
import duckdb
|
|
1116
|
+
conn = duckdb.connect('.flock/traces.duckdb', read_only=True)
|
|
1117
|
+
|
|
1118
|
+
# Get last 10 executions of same operation
|
|
1119
|
+
perf_history = conn.execute("""
|
|
1120
|
+
SELECT
|
|
1121
|
+
trace_id,
|
|
1122
|
+
start_time,
|
|
1123
|
+
duration_ms
|
|
1124
|
+
FROM spans
|
|
1125
|
+
WHERE name = 'DSPyEngine.evaluate' -- or any operation
|
|
1126
|
+
ORDER BY start_time DESC
|
|
1127
|
+
LIMIT 10
|
|
1128
|
+
""").fetchall()
|
|
1129
|
+
|
|
1130
|
+
# Calculate average and detect outliers
|
|
1131
|
+
durations = [p[2] for p in perf_history]
|
|
1132
|
+
avg = sum(durations) / len(durations)
|
|
1133
|
+
latest = durations[0]
|
|
1134
|
+
|
|
1135
|
+
print(f"Latest: {latest:.2f}ms")
|
|
1136
|
+
print(f"Average: {avg:.2f}ms")
|
|
1137
|
+
print(f"Change: {((latest / avg - 1) * 100):+.1f}%")
|
|
1138
|
+
|
|
1139
|
+
if latest > avg * 1.5:
|
|
1140
|
+
print("⚠️ Performance regression detected!")
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
### Best Practices for AI Agents
|
|
1144
|
+
|
|
1145
|
+
**✅ DO:**
|
|
1146
|
+
- **Always enable tracing** before running code to debug
|
|
1147
|
+
- **Start with overview queries** (get all traces, find latest)
|
|
1148
|
+
- **Work from general to specific** (trace → spans → attributes → I/O)
|
|
1149
|
+
- **Use read-only connections** (`read_only=True`)
|
|
1150
|
+
- **Close connections** when done
|
|
1151
|
+
- **Clear old traces** periodically: `Flock.clear_traces()`
|
|
1152
|
+
- **Use correlation IDs** to track related operations
|
|
1153
|
+
|
|
1154
|
+
**❌ DON'T:**
|
|
1155
|
+
- Don't modify code just to add logging - query traces instead
|
|
1156
|
+
- Don't guess at execution flow - trace database has the truth
|
|
1157
|
+
- Don't skip trace analysis for "obvious" bugs - verify with data
|
|
1158
|
+
- Don't forget to check `status_description` for error details
|
|
1159
|
+
- Don't ignore timing data - it reveals bottlenecks
|
|
1160
|
+
|
|
1161
|
+
### Tracing-First Testing Workflow
|
|
1162
|
+
|
|
1163
|
+
When writing or debugging tests:
|
|
1164
|
+
|
|
1165
|
+
1. **Run test with tracing enabled**
|
|
1166
|
+
```bash
|
|
1167
|
+
FLOCK_AUTO_TRACE=true FLOCK_TRACE_FILE=true uv run pytest tests/test_file.py -v
|
|
1168
|
+
```
|
|
1169
|
+
|
|
1170
|
+
2. **Query trace to see what actually happened**
|
|
1171
|
+
```python
|
|
1172
|
+
# Get test execution trace
|
|
1173
|
+
trace_id = conn.execute("SELECT trace_id FROM spans GROUP BY trace_id ORDER BY MIN(start_time) DESC LIMIT 1").fetchone()[0]
|
|
1174
|
+
```
|
|
1175
|
+
|
|
1176
|
+
3. **Verify assertions match reality**
|
|
1177
|
+
```python
|
|
1178
|
+
# What did the agent actually produce?
|
|
1179
|
+
actual = conn.execute("SELECT json_extract(attributes, '$.output.value') FROM spans WHERE trace_id = ? AND name = 'Agent.execute'", [trace_id]).fetchone()
|
|
1180
|
+
|
|
1181
|
+
# Does it match test expectations?
|
|
1182
|
+
expected = "BugDiagnosis artifact with severity='Critical'"
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
4. **Debug failures with exact I/O data**
|
|
1186
|
+
```python
|
|
1187
|
+
# Get the exact input that caused test failure
|
|
1188
|
+
failure_input = conn.execute("""
|
|
1189
|
+
SELECT json_extract(attributes, '$.input.artifacts')
|
|
1190
|
+
FROM spans WHERE trace_id = ? AND status_code = 'ERROR'
|
|
1191
|
+
""", [trace_id]).fetchone()
|
|
1192
|
+
```
|
|
1193
|
+
|
|
1194
|
+
### Quick Start: Enable Tracing
|
|
1195
|
+
|
|
1196
|
+
```bash
|
|
1197
|
+
# Enable auto-tracing (add to .env or export)
|
|
1198
|
+
FLOCK_AUTO_TRACE=true # Enable tracing for all operations
|
|
1199
|
+
FLOCK_TRACE_FILE=true # Store traces in DuckDB
|
|
1200
|
+
|
|
1201
|
+
# Run your application
|
|
1202
|
+
python examples/showcase/01_declarative_pizza.py
|
|
1203
|
+
|
|
1204
|
+
# Traces stored in: .flock/traces.duckdb
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
### 🆕 Unified Tracing with traced_run()
|
|
1208
|
+
|
|
1209
|
+
**New in v0.5.0**: Wrap entire workflows in a single parent trace for better observability!
|
|
1210
|
+
|
|
1211
|
+
```python
|
|
1212
|
+
# ✅ Unified trace
|
|
1213
|
+
async with flock.traced_run("pizza_workflow"):
|
|
1214
|
+
await flock.publish(pizza_idea)
|
|
1215
|
+
await flock.run_until_idle()
|
|
1216
|
+
```
|
|
1217
|
+
|
|
1218
|
+
**Result**: Single trace with proper hierarchy
|
|
1219
|
+
|
|
1220
|
+
### 🗑️ Clearing Traces
|
|
1221
|
+
|
|
1222
|
+
Clear trace database for fresh debug sessions:
|
|
1223
|
+
|
|
1224
|
+
```python
|
|
1225
|
+
# Clear all traces
|
|
1226
|
+
result = Flock.clear_traces()
|
|
1227
|
+
print(f"Deleted {result['deleted_count']} spans")
|
|
1228
|
+
```
|
|
1229
|
+
|
|
1230
|
+
📖 **Full tracing documentation**: [docs/UNIFIED_TRACING.md](docs/UNIFIED_TRACING.md)
|
|
1231
|
+
|
|
1232
|
+
---
|
|
1233
|
+
|
|
1234
|
+
## ❓ FAQ for AI Agents
|
|
1235
|
+
|
|
1236
|
+
### Q: How do I debug or test Flock code?
|
|
1237
|
+
|
|
1238
|
+
**⚠️ ALWAYS START WITH TRACING!**
|
|
1239
|
+
|
|
1240
|
+
Quick debugging workflow:
|
|
1241
|
+
```bash
|
|
1242
|
+
# 1. Enable tracing
|
|
1243
|
+
export FLOCK_AUTO_TRACE=true FLOCK_TRACE_FILE=true
|
|
1244
|
+
|
|
1245
|
+
# 2. Run the code
|
|
1246
|
+
uv run python examples/path/to/script.py
|
|
1247
|
+
|
|
1248
|
+
# 3. Query trace database
|
|
1249
|
+
uv run python -c "
|
|
1250
|
+
import duckdb
|
|
1251
|
+
conn = duckdb.connect('.flock/traces.duckdb', read_only=True)
|
|
1252
|
+
|
|
1253
|
+
# Get latest trace
|
|
1254
|
+
trace = conn.execute('''
|
|
1255
|
+
SELECT trace_id, COUNT(*) as spans,
|
|
1256
|
+
(MAX(end_time)-MIN(start_time))/1000000.0 as duration_ms
|
|
1257
|
+
FROM spans GROUP BY trace_id
|
|
1258
|
+
ORDER BY MIN(start_time) DESC LIMIT 1
|
|
1259
|
+
''').fetchone()
|
|
1260
|
+
|
|
1261
|
+
print(f'Trace: {trace[0][:32]}...')
|
|
1262
|
+
print(f'Spans: {trace[1]}, Duration: {trace[2]:.2f}ms')
|
|
1263
|
+
|
|
1264
|
+
# Get execution flow
|
|
1265
|
+
flow = conn.execute('''
|
|
1266
|
+
SELECT name, duration_ms, status_code
|
|
1267
|
+
FROM spans WHERE trace_id = ?
|
|
1268
|
+
ORDER BY start_time
|
|
1269
|
+
''', [trace[0]]).fetchall()
|
|
1270
|
+
|
|
1271
|
+
for op in flow:
|
|
1272
|
+
status = '✅' if op[2] == 'OK' else '❌'
|
|
1273
|
+
print(f'{status} {op[0]}: {op[1]:.2f}ms')
|
|
1274
|
+
"
|
|
1275
|
+
```
|
|
1276
|
+
|
|
1277
|
+
📖 **Complete guide:** [🤖 FOR AI AGENTS: Tracing is Your PRIMARY Debugging Tool](#-for-ai-agents-tracing-is-your-primary-debugging-tool) (scroll up in this file)
|
|
1278
|
+
|
|
1279
|
+
### Q: Where should I save new files?
|
|
1280
|
+
|
|
1281
|
+
**⚠️ CRITICAL: NEVER save files to the project root directory!**
|
|
1282
|
+
|
|
1283
|
+
Always use the appropriate subdirectory:
|
|
1284
|
+
- **Tests**: `/tests` - All test files only
|
|
1285
|
+
- **Source Code**: `/src/flock` - Production code following refactored module structure:
|
|
1286
|
+
- `/src/flock/core/` - Core orchestration and agents (Phase 2)
|
|
1287
|
+
- `/src/flock/orchestrator/` - Orchestrator modules (Phase 3 + 5A)
|
|
1288
|
+
- `/src/flock/agent/` - Agent modules (Phase 4)
|
|
1289
|
+
- `/src/flock/components/` - Component library
|
|
1290
|
+
- `/src/flock/engines/` - Engine implementations
|
|
1291
|
+
- `/src/flock/utils/` - Utility modules (Phase 1)
|
|
1292
|
+
- **Documentation**: `/docs` - Documentation only
|
|
1293
|
+
- `/docs/patterns/` - Code patterns and best practices
|
|
1294
|
+
- `/docs/guides/` - User guides and tutorials
|
|
1295
|
+
- `/docs/refactor/` - Refactoring documentation (Phase 1-7)
|
|
1296
|
+
- **Examples**: `/examples` - Example scripts only
|
|
1297
|
+
- **Frontend**: `src/flock/frontend/src` - React components and frontend code
|
|
1298
|
+
|
|
1299
|
+
**Never create files in the root directory** - it should only contain configuration files like `pyproject.toml`, `README.md`, etc.
|
|
1300
|
+
|
|
1301
|
+
**📐 See [Architecture Overview](docs/architecture.md) for complete module organization details.**
|
|
1302
|
+
|
|
1303
|
+
### Q: How do I add a new dependency?
|
|
1304
|
+
|
|
1305
|
+
```bash
|
|
1306
|
+
# Python
|
|
1307
|
+
uv add package-name
|
|
1308
|
+
|
|
1309
|
+
# Frontend
|
|
1310
|
+
cd frontend && npm install package-name
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
📖 **Full guide:** [Dependencies Guide](docs/ai-agents/dependencies.md)
|
|
1314
|
+
|
|
1315
|
+
### Q: How do I run a specific test?
|
|
1316
|
+
|
|
1317
|
+
```bash
|
|
1318
|
+
# Backend
|
|
1319
|
+
uv run pytest tests/test_file.py::test_name -v
|
|
1320
|
+
|
|
1321
|
+
# Frontend
|
|
1322
|
+
cd frontend && npm test -- test_name
|
|
1323
|
+
```
|
|
1324
|
+
|
|
1325
|
+
### Q: How do I start the dashboard?
|
|
1326
|
+
|
|
1327
|
+
```python
|
|
1328
|
+
await orchestrator.serve(dashboard=True)
|
|
1329
|
+
```
|
|
1330
|
+
|
|
1331
|
+
📖 **Full guide:** [Frontend Guide](docs/ai-agents/frontend.md)
|
|
1332
|
+
|
|
1333
|
+
### Q: How do I test UI features and debug dashboard issues?
|
|
1334
|
+
|
|
1335
|
+
**Use playwright-mcp with dashboard examples for comprehensive manual UI testing.**
|
|
1336
|
+
|
|
1337
|
+
#### Step-by-Step Testing Workflow
|
|
1338
|
+
|
|
1339
|
+
**1. Start the Dashboard Example**
|
|
1340
|
+
```bash
|
|
1341
|
+
# Run in background to keep testing
|
|
1342
|
+
uv run python examples/03-the-dashboard/01_declarative_pizza.py
|
|
1343
|
+
```
|
|
1344
|
+
|
|
1345
|
+
Wait for these success indicators in the output:
|
|
1346
|
+
- `[Dashboard] Production build completed`
|
|
1347
|
+
- `INFO: Uvicorn running on http://127.0.0.1:8344`
|
|
1348
|
+
- `[Dashboard] Browser launched successfully`
|
|
1349
|
+
|
|
1350
|
+
**2. Navigate and Verify Initial Load**
|
|
1351
|
+
```python
|
|
1352
|
+
# Use playwright-mcp tools
|
|
1353
|
+
mcp__playwright__browser_navigate(url="http://localhost:8344")
|
|
1354
|
+
```
|
|
1355
|
+
|
|
1356
|
+
**✅ What to verify:**
|
|
1357
|
+
- Page title: "🦆🐓 Flock 🐤🐧"
|
|
1358
|
+
- WebSocket status (top right): **"Connected"** (green)
|
|
1359
|
+
- Two view buttons: "Agent View" (active) and "Blackboard View"
|
|
1360
|
+
- Control buttons: Publish, Agent Details, Filters, Settings
|
|
1361
|
+
|
|
1362
|
+
**3. Test Agent View**
|
|
1363
|
+
|
|
1364
|
+
Take a snapshot to see the agent graph:
|
|
1365
|
+
```python
|
|
1366
|
+
mcp__playwright__browser_snapshot()
|
|
1367
|
+
```
|
|
1368
|
+
|
|
1369
|
+
**✅ What to verify in Agent View:**
|
|
1370
|
+
- Agent nodes displayed (e.g., `pizza_master`)
|
|
1371
|
+
- Each node shows:
|
|
1372
|
+
- Agent name and status (should be "idle" initially)
|
|
1373
|
+
- Input types with count (e.g., ↓ 0 __main__.MyDreamPizza)
|
|
1374
|
+
- Output types with count (e.g., ↑ 0 __main__.Pizza)
|
|
1375
|
+
- React Flow controls (zoom in/out, fit view, mini-map)
|
|
1376
|
+
|
|
1377
|
+
**4. Open Agent Details Panel**
|
|
1378
|
+
```python
|
|
1379
|
+
# Click the Agent Details button
|
|
1380
|
+
mcp__playwright__browser_click(element="Agent Details button", ref="<ref>")
|
|
1381
|
+
```
|
|
1382
|
+
|
|
1383
|
+
**✅ What to verify:**
|
|
1384
|
+
- Panel opens showing agent name
|
|
1385
|
+
- Three tabs: "Live Output", "Message History", "Run Status"
|
|
1386
|
+
- Shows "Idle - no output" initially
|
|
1387
|
+
|
|
1388
|
+
**5. Test Publishing an Artifact**
|
|
1389
|
+
|
|
1390
|
+
```python
|
|
1391
|
+
# Step 1: Select artifact type
|
|
1392
|
+
mcp__playwright__browser_select_option(
|
|
1393
|
+
element="Artifact Type dropdown",
|
|
1394
|
+
ref="<ref>",
|
|
1395
|
+
values=["__main__.MyDreamPizza"]
|
|
1396
|
+
)
|
|
1397
|
+
```
|
|
1398
|
+
|
|
1399
|
+
**✅ What to verify after selecting type:**
|
|
1400
|
+
- Form dynamically generates input fields based on artifact schema
|
|
1401
|
+
- For MyDreamPizza: Should show "Pizza Idea" textbox
|
|
1402
|
+
|
|
1403
|
+
```python
|
|
1404
|
+
# Step 2: Fill in the input
|
|
1405
|
+
mcp__playwright__browser_type(
|
|
1406
|
+
element="Pizza Idea textbox",
|
|
1407
|
+
ref="<ref>",
|
|
1408
|
+
text="a spicy Hawaiian pizza with jalapeños and pineapple"
|
|
1409
|
+
)
|
|
1410
|
+
|
|
1411
|
+
# Step 3: Publish
|
|
1412
|
+
mcp__playwright__browser_click(
|
|
1413
|
+
element="Publish Artifact button",
|
|
1414
|
+
ref="<ref>"
|
|
1415
|
+
)
|
|
1416
|
+
```
|
|
1417
|
+
|
|
1418
|
+
**✅ What to verify after publishing:**
|
|
1419
|
+
- Agent status changes: "idle" → "running" → "idle"
|
|
1420
|
+
- Input count increases: ↓ 0 → ↓ 1
|
|
1421
|
+
- Output count increases: ↑ 0 → ↑ 1
|
|
1422
|
+
- **External node appears** on the graph (shows who published the artifact)
|
|
1423
|
+
- Edge connects external → pizza_master
|
|
1424
|
+
|
|
1425
|
+
**6. Monitor Live Execution**
|
|
1426
|
+
|
|
1427
|
+
**✅ What to verify in Agent Details panel:**
|
|
1428
|
+
- Event counter increases (e.g., "316 events")
|
|
1429
|
+
- Live streaming output appears token-by-token
|
|
1430
|
+
- Console shows WebSocket messages: `[WebSocket] Streaming output: {...}`
|
|
1431
|
+
- Final output shows complete structured data
|
|
1432
|
+
- "--- End of output ---" marker when complete
|
|
1433
|
+
|
|
1434
|
+
**7. Test Blackboard View**
|
|
1435
|
+
```python
|
|
1436
|
+
# Switch to Blackboard View
|
|
1437
|
+
mcp__playwright__browser_click(
|
|
1438
|
+
element="Blackboard View button",
|
|
1439
|
+
ref="<ref>"
|
|
1440
|
+
)
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
**✅ What to verify in Blackboard View:**
|
|
1444
|
+
- **Input artifact node** showing:
|
|
1445
|
+
- Type: `__main__.MyDreamPizza`
|
|
1446
|
+
- Producer: "by: external"
|
|
1447
|
+
- Timestamp
|
|
1448
|
+
- Full JSON payload (expandable)
|
|
1449
|
+
- **Output artifact node** showing:
|
|
1450
|
+
- Type: `__main__.Pizza`
|
|
1451
|
+
- Producer: "by: pizza_master"
|
|
1452
|
+
- Timestamp
|
|
1453
|
+
- Complete structured data with all fields
|
|
1454
|
+
- **Edge** connecting input → output artifacts
|
|
1455
|
+
- Data is fully browsable (can expand/collapse nested objects)
|
|
1456
|
+
|
|
1457
|
+
**8. Take Screenshots for Verification**
|
|
1458
|
+
```python
|
|
1459
|
+
# Capture key states for visual verification
|
|
1460
|
+
mcp__playwright__browser_take_screenshot(filename="dashboard-test.png")
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
#### Common Issues and Troubleshooting
|
|
1464
|
+
|
|
1465
|
+
**Issue: Dashboard doesn't load**
|
|
1466
|
+
- Check: Backend server started? Look for "Uvicorn running" message
|
|
1467
|
+
- Check: Frontend build completed? Look for "Production build completed"
|
|
1468
|
+
- Solution: Wait 5-10 seconds after starting for build to complete
|
|
1469
|
+
|
|
1470
|
+
**Issue: WebSocket shows "Disconnected"**
|
|
1471
|
+
- Check: Console for WebSocket errors
|
|
1472
|
+
- Check: Server logs for WebSocket connection messages
|
|
1473
|
+
- Solution: Refresh page, verify server is running
|
|
1474
|
+
|
|
1475
|
+
**Issue: No live output during agent execution**
|
|
1476
|
+
- Check: Agent Details panel is open
|
|
1477
|
+
- Check: "Live Output" tab is active
|
|
1478
|
+
- Check: Console shows `[WebSocket] Streaming output` messages
|
|
1479
|
+
- Solution: Verify WebSocket connection status
|
|
1480
|
+
|
|
1481
|
+
**Issue: Artifacts not appearing in Blackboard View**
|
|
1482
|
+
- Check: Did agent execution complete? (status back to "idle")
|
|
1483
|
+
- Check: Output count increased? (↑ 1)
|
|
1484
|
+
- Solution: Switch back to Agent View to verify execution, then return to Blackboard View
|
|
1485
|
+
|
|
1486
|
+
#### Why Manual Testing with Playwright-MCP?
|
|
1487
|
+
|
|
1488
|
+
- ✅ **Live testing** - Real dashboard with actual agents executing
|
|
1489
|
+
- ✅ **Visual verification** - See exactly what users see
|
|
1490
|
+
- ✅ **WebSocket testing** - Verify real-time streaming works correctly
|
|
1491
|
+
- ✅ **Full workflow** - Test complete user journey from publish → execute → view results
|
|
1492
|
+
- ✅ **Screenshot capture** - Document UI state for debugging/documentation
|
|
1493
|
+
- ✅ **Interactive debugging** - Click, type, inspect like a real user
|
|
1494
|
+
|
|
1495
|
+
📖 **Dashboard examples:** [`examples/02-dashboard/`](examples/02-dashboard/)
|
|
1496
|
+
|
|
1497
|
+
---
|
|
1498
|
+
|
|
1499
|
+
#### Advanced Dashboard Testing: Multi-Agent Cascades & Conditional Consumption
|
|
1500
|
+
|
|
1501
|
+
**Test with:** `examples/03-the-dashboard/02-dashboard-edge-cases.py`
|
|
1502
|
+
|
|
1503
|
+
This example demonstrates advanced features not visible in simple single-agent workflows.
|
|
1504
|
+
|
|
1505
|
+
**1. Use Auto Layout for Complex Graphs**
|
|
1506
|
+
|
|
1507
|
+
When testing with 3+ agents, use the context menu to organize the graph:
|
|
1508
|
+
|
|
1509
|
+
```python
|
|
1510
|
+
# After navigating to dashboard
|
|
1511
|
+
# Right-click on the canvas (not on a node)
|
|
1512
|
+
mcp__playwright__browser_click(element="Canvas area", ref="<ref>", button="right")
|
|
1513
|
+
|
|
1514
|
+
# Click Auto Layout from context menu
|
|
1515
|
+
mcp__playwright__browser_click(element="Auto Layout button", ref="<ref>")
|
|
1516
|
+
```
|
|
1517
|
+
|
|
1518
|
+
**✅ What to verify:**
|
|
1519
|
+
- Agents arranged in clean vertical or horizontal hierarchy
|
|
1520
|
+
- No overlapping nodes
|
|
1521
|
+
- Edges clearly visible between agents
|
|
1522
|
+
|
|
1523
|
+
**2. Test Conditional Consumption (Lambda Filters)**
|
|
1524
|
+
|
|
1525
|
+
This example has agents with `where` clauses that filter which artifacts they consume:
|
|
1526
|
+
|
|
1527
|
+
```python
|
|
1528
|
+
# In the code:
|
|
1529
|
+
chapter_agent.consumes(Review, where=lambda r: r.score >= 9) # Only high scores
|
|
1530
|
+
book_idea_agent.consumes(Review, where=lambda r: r.score <= 8) # Only low scores (feedback loop)
|
|
1531
|
+
```
|
|
1532
|
+
|
|
1533
|
+
**✅ What to verify after publishing Idea:**
|
|
1534
|
+
- **Edge labels show filtered counts**: e.g., `__main__.Review(1)` means "1 Review consumed out of 3 total"
|
|
1535
|
+
- **Input counts reflect actual consumption**: chapter_agent shows ↓ 1 Review (not ↓ 3)
|
|
1536
|
+
- **Feedback loops work**: book_idea_agent consumes both Idea AND Review artifacts
|
|
1537
|
+
|
|
1538
|
+
**3. Monitor Multi-Agent Cascade Execution**
|
|
1539
|
+
|
|
1540
|
+
Expected workflow for edge cases example:
|
|
1541
|
+
```
|
|
1542
|
+
1. Publish Idea artifact
|
|
1543
|
+
2. book_idea_agent: ↓ 1 Idea → ↑ 3 BookHook (produces multiple outputs!)
|
|
1544
|
+
3. reviewer_agent: ↓ 3 BookHook → ↑ 3 Review (processes each hook)
|
|
1545
|
+
4. chapter_agent: ↓ 1 Review → ↑ 1 BookOutline (filtered: only score >= 9)
|
|
1546
|
+
5. book_idea_agent: ↓ 2 Review → ↑ 0 BookHook (feedback loop for low scores)
|
|
1547
|
+
```
|
|
1548
|
+
|
|
1549
|
+
**✅ What to verify during cascade:**
|
|
1550
|
+
- Agent statuses transition: idle → running → idle
|
|
1551
|
+
- Counters update in real-time as each agent completes
|
|
1552
|
+
- External node persists showing initial publisher
|
|
1553
|
+
- Edges appear/update showing data flow
|
|
1554
|
+
|
|
1555
|
+
**4. Handle Large Artifact Counts**
|
|
1556
|
+
|
|
1557
|
+
**⚠️ IMPORTANT**: When page has 8+ artifacts, `browser_snapshot()` exceeds 25K token limit and fails.
|
|
1558
|
+
|
|
1559
|
+
**Solution**: Use `browser_take_screenshot()` for visual verification instead:
|
|
1560
|
+
|
|
1561
|
+
```python
|
|
1562
|
+
# ❌ This will fail with many artifacts
|
|
1563
|
+
mcp__playwright__browser_snapshot()
|
|
1564
|
+
|
|
1565
|
+
# ✅ Use screenshots instead
|
|
1566
|
+
mcp__playwright__browser_take_screenshot(filename="cascade-state.png")
|
|
1567
|
+
```
|
|
1568
|
+
|
|
1569
|
+
**5. Verify Final State in Blackboard View**
|
|
1570
|
+
|
|
1571
|
+
```python
|
|
1572
|
+
# Switch to Blackboard View
|
|
1573
|
+
mcp__playwright__browser_click(element="Blackboard View button", ref="<ref>")
|
|
1574
|
+
|
|
1575
|
+
# Take screenshot (snapshot will fail with many artifacts)
|
|
1576
|
+
mcp__playwright__browser_take_screenshot(filename="blackboard-artifacts.png")
|
|
1577
|
+
```
|
|
1578
|
+
|
|
1579
|
+
**✅ What to verify:**
|
|
1580
|
+
- All produced artifacts visible as nodes
|
|
1581
|
+
- **1 Idea** → **3 BookHooks** → **3 Reviews** → **1 BookOutline**
|
|
1582
|
+
- Edges show complete transformation chain
|
|
1583
|
+
- Final artifact (BookOutline) contains expected structured data
|
|
1584
|
+
- Timestamps show execution order
|
|
1585
|
+
|
|
1586
|
+
#### Expected Execution Time
|
|
1587
|
+
|
|
1588
|
+
**Simple example (01_declarative_pizza.py)**: ~5 seconds (1 agent, 1 artifact)
|
|
1589
|
+
**Edge cases (02-dashboard-edge-cases.py)**: ~60 seconds (3 agents, 8 artifacts, feedback loop)
|
|
1590
|
+
|
|
1591
|
+
Plan your testing time accordingly!
|
|
1592
|
+
|
|
1593
|
+
#### Key Dashboard Features Learned
|
|
1594
|
+
|
|
1595
|
+
**Auto Layout** ⭐
|
|
1596
|
+
- Access via right-click context menu
|
|
1597
|
+
- Automatically organizes complex agent graphs
|
|
1598
|
+
- Essential for 3+ agent workflows
|
|
1599
|
+
|
|
1600
|
+
**Filtered Edge Labels** ⭐
|
|
1601
|
+
- Shows actual consumed count vs total available
|
|
1602
|
+
- Format: `ArtifactType(consumed_count)`
|
|
1603
|
+
- Makes conditional consumption transparent
|
|
1604
|
+
|
|
1605
|
+
**Feedback Loops** ⭐
|
|
1606
|
+
- Agents can consume multiple artifact types
|
|
1607
|
+
- Low-scoring Reviews loop back to book_idea_agent
|
|
1608
|
+
- Counts accumulate correctly across iterations
|
|
1609
|
+
|
|
1610
|
+
**Real-time Updates** ⭐
|
|
1611
|
+
- Status changes: idle → running → idle
|
|
1612
|
+
- Counters increment as artifacts produced/consumed
|
|
1613
|
+
- WebSocket delivers updates without page refresh
|
|
1614
|
+
|
|
1615
|
+
📖 **Dashboard examples:** [`examples/02-dashboard/`](examples/02-dashboard/)
|
|
1616
|
+
|
|
1617
|
+
---
|
|
1618
|
+
|
|
1619
|
+
### Q: How do I use unified tracing?
|
|
1620
|
+
|
|
1621
|
+
```python
|
|
1622
|
+
# Wrap workflows in a single trace
|
|
1623
|
+
async with flock.traced_run("workflow_name"):
|
|
1624
|
+
await flock.publish(data)
|
|
1625
|
+
await flock.run_until_idle()
|
|
1626
|
+
|
|
1627
|
+
# Clear traces for fresh debug session
|
|
1628
|
+
result = Flock.clear_traces()
|
|
1629
|
+
```
|
|
1630
|
+
|
|
1631
|
+
📖 **Full guide:** [docs/UNIFIED_TRACING.md](docs/UNIFIED_TRACING.md)
|
|
1632
|
+
|
|
1633
|
+
### Q: Where should I add new tests?
|
|
1634
|
+
|
|
1635
|
+
Add to existing test file if relevant, or create new file following naming convention `test_<module>.py` for backend, `<name>.test.tsx` for frontend.
|
|
1636
|
+
|
|
1637
|
+
### Q: What Python version features can I use?
|
|
1638
|
+
|
|
1639
|
+
Python 3.12+, so you can use:
|
|
1640
|
+
- `match`/`case` statements
|
|
1641
|
+
- `TaskGroup` for parallel execution (see [docs/patterns/async_patterns.md](docs/patterns/async_patterns.md))
|
|
1642
|
+
- Improved type hints (`list[str]` not `List[str]`)
|
|
1643
|
+
- Exception groups with `except*` (see [docs/patterns/error_handling.md](docs/patterns/error_handling.md))
|
|
1644
|
+
|
|
1645
|
+
**⚠️ CRITICAL:** Follow error handling and async patterns documented in `/docs/patterns/` - these are REQUIRED for all new code.
|
|
1646
|
+
|
|
1647
|
+
### Q: How do I debug WebSocket issues?
|
|
1648
|
+
|
|
1649
|
+
Check browser console for WebSocket logs, use Network tab to inspect connection, and verify backend WebSocket server is running on correct port.
|
|
1650
|
+
|
|
1651
|
+
---
|
|
1652
|
+
|
|
1653
|
+
## 🎯 Quick Reference
|
|
1654
|
+
|
|
1655
|
+
### Essential Commands
|
|
1656
|
+
|
|
1657
|
+
```bash
|
|
1658
|
+
# Setup
|
|
1659
|
+
poe install # Install all dependencies
|
|
1660
|
+
|
|
1661
|
+
# Development
|
|
1662
|
+
poe build # Build project
|
|
1663
|
+
poe lint # Lint code
|
|
1664
|
+
poe format # Format code
|
|
1665
|
+
|
|
1666
|
+
# Testing
|
|
1667
|
+
poe test # Run tests
|
|
1668
|
+
poe test-cov # Run with coverage
|
|
1669
|
+
poe test-critical # Run critical path tests
|
|
1670
|
+
|
|
1671
|
+
# Frontend
|
|
1672
|
+
cd frontend
|
|
1673
|
+
npm run dev # Start dev server
|
|
1674
|
+
npm test # Run frontend tests
|
|
1675
|
+
npm run build # Build for production
|
|
1676
|
+
|
|
1677
|
+
# UI Testing (with playwright-mcp)
|
|
1678
|
+
uv run python examples/03-the-dashboard/01_declarative_pizza.py # Start dashboard
|
|
1679
|
+
# Then use playwright-mcp to interact with UI for manual testing
|
|
1680
|
+
```
|
|
1681
|
+
|
|
1682
|
+
### Code Snippets
|
|
1683
|
+
|
|
1684
|
+
**Create orchestrator:**
|
|
1685
|
+
```python
|
|
1686
|
+
from flock import Flock # ✅ Correct import (refactored in Phase 3)
|
|
1687
|
+
orchestrator = Flock("openai/gpt-4o")
|
|
1688
|
+
```
|
|
1689
|
+
|
|
1690
|
+
**Define agent:**
|
|
1691
|
+
```python
|
|
1692
|
+
agent = (
|
|
1693
|
+
orchestrator.agent("name")
|
|
1694
|
+
.description("What it does")
|
|
1695
|
+
.consumes(InputType)
|
|
1696
|
+
.publishes(OutputType)
|
|
1697
|
+
)
|
|
1698
|
+
```
|
|
1699
|
+
|
|
1700
|
+
**Run agent:**
|
|
1701
|
+
```python
|
|
1702
|
+
await orchestrator.arun(agent, input_data)
|
|
1703
|
+
```
|
|
1704
|
+
|
|
1705
|
+
**Fan-out publishing (multiple outputs):**
|
|
1706
|
+
```python
|
|
1707
|
+
# Single-type fan-out: Generate 10 outputs per execution
|
|
1708
|
+
agent = (
|
|
1709
|
+
orchestrator.agent("generator")
|
|
1710
|
+
.consumes(InputType)
|
|
1711
|
+
.publishes(OutputType, fan_out=10)
|
|
1712
|
+
)
|
|
1713
|
+
|
|
1714
|
+
# Multi-output fan-out: Generate 3 of EACH type = 9 total artifacts in ONE LLM call!
|
|
1715
|
+
multi_master = (
|
|
1716
|
+
orchestrator.agent("multi_master")
|
|
1717
|
+
.consumes(Idea)
|
|
1718
|
+
.publishes(Movie, MovieScript, MovieCampaign, fan_out=3)
|
|
1719
|
+
)
|
|
1720
|
+
# Result: 3 Movies + 3 MovieScripts + 3 MovieCampaigns = 9 artifacts
|
|
1721
|
+
# 89% cost savings vs 9 separate calls + perfect context alignment!
|
|
1722
|
+
|
|
1723
|
+
# With filtering (reduce noise)
|
|
1724
|
+
agent.publishes(OutputType, fan_out=20, where=lambda o: o.score >= 8.0)
|
|
1725
|
+
|
|
1726
|
+
# With validation (enforce quality)
|
|
1727
|
+
agent.publishes(
|
|
1728
|
+
OutputType,
|
|
1729
|
+
fan_out=10,
|
|
1730
|
+
validate=lambda o: o.field in ["valid", "values"]
|
|
1731
|
+
)
|
|
1732
|
+
|
|
1733
|
+
# With dynamic visibility (per-artifact access control)
|
|
1734
|
+
agent.publishes(
|
|
1735
|
+
OutputType,
|
|
1736
|
+
fan_out=5,
|
|
1737
|
+
visibility=lambda o: PrivateVisibility(agents=[o.recipient])
|
|
1738
|
+
)
|
|
1739
|
+
```
|
|
1740
|
+
|
|
1741
|
+
**Unified tracing:**
|
|
1742
|
+
```python
|
|
1743
|
+
# Wrap workflow in single trace
|
|
1744
|
+
async with flock.traced_run("workflow_name"):
|
|
1745
|
+
await flock.publish(data)
|
|
1746
|
+
await flock.run_until_idle()
|
|
1747
|
+
|
|
1748
|
+
# Clear traces
|
|
1749
|
+
Flock.clear_traces()
|
|
1750
|
+
```
|
|
1751
|
+
|
|
1752
|
+
**Start dashboard:**
|
|
1753
|
+
```python
|
|
1754
|
+
await orchestrator.serve(dashboard=True)
|
|
1755
|
+
```
|
|
1756
|
+
|
|
1757
|
+
---
|
|
1758
|
+
|
|
1759
|
+
## 📞 Getting Help
|
|
1760
|
+
|
|
1761
|
+
### Documentation
|
|
1762
|
+
|
|
1763
|
+
**AI Agent Guides (this repo):**
|
|
1764
|
+
- **[Architecture Overview](docs/architecture.md)** - Complete system design, module organization, Phase 1-7 refactoring ⭐ **MUST READ**
|
|
1765
|
+
- **[Error Handling Patterns](docs/patterns/error_handling.md)** - Production error handling guide ⭐ **REQUIRED**
|
|
1766
|
+
- **[Async Patterns](docs/patterns/async_patterns.md)** - Async/await best practices ⭐ **REQUIRED**
|
|
1767
|
+
- **[Architecture Guide](docs/ai-agents/architecture.md)** - Core architecture, project structure, code style
|
|
1768
|
+
- **[Development Workflow](docs/ai-agents/development.md)** - Testing, quality standards, versioning
|
|
1769
|
+
- **[Frontend Guide](docs/ai-agents/frontend.md)** - Dashboard usage, frontend development
|
|
1770
|
+
- **[Dependencies Guide](docs/ai-agents/dependencies.md)** - Package management, UV commands
|
|
1771
|
+
- **[Common Tasks](docs/ai-agents/common-tasks.md)** - Adding agents/components, performance
|
|
1772
|
+
|
|
1773
|
+
**Additional Documentation:**
|
|
1774
|
+
- **Contributing Guide:** [`CONTRIBUTING.md`](CONTRIBUTING.md) - Complete contribution workflow
|
|
1775
|
+
- **Versioning Guide:** [`docs/VERSIONING.md`](docs/VERSIONING.md) - Smart version bumping
|
|
1776
|
+
- **Pre-commit Hooks:** [`docs/PRE_COMMIT_HOOKS.md`](docs/PRE_COMMIT_HOOKS.md) - Quality automation
|
|
1777
|
+
- **Unified Tracing:** [`docs/UNIFIED_TRACING.md`](docs/UNIFIED_TRACING.md) - Workflow tracing & trace management
|
|
1778
|
+
- **Examples:** [`examples/`](examples/) - Working code examples
|
|
1779
|
+
- **Analysis Documents:** [`docs/patterns/`](docs/patterns/)
|
|
1780
|
+
|
|
1781
|
+
---
|
|
1782
|
+
|
|
1783
|
+
**Welcome to the team! Let's build the future of AI agent orchestration together.** 🚀
|
|
1784
|
+
|
|
1785
|
+
---
|
|
1786
|
+
|
|
1787
|
+
*Last updated: October 19, 2025*
|
|
1788
|
+
*This file follows the modern AGENTS.md format for AI coding agents.*
|
|
1789
|
+
*Reflects Phase 1-7 refactoring with updated module organization and patterns.*
|