flock-core 0.3.23__py3-none-any.whl → 0.3.31__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/__init__.py +23 -11
- flock/cli/constants.py +2 -4
- flock/cli/create_flock.py +220 -1
- flock/cli/execute_flock.py +200 -0
- flock/cli/load_flock.py +27 -7
- flock/cli/loaded_flock_cli.py +202 -0
- flock/cli/manage_agents.py +443 -0
- flock/cli/view_results.py +29 -0
- flock/cli/yaml_editor.py +283 -0
- flock/core/__init__.py +2 -2
- flock/core/api/__init__.py +11 -0
- flock/core/api/endpoints.py +222 -0
- flock/core/api/main.py +237 -0
- flock/core/api/models.py +34 -0
- flock/core/api/run_store.py +72 -0
- flock/core/api/ui/__init__.py +0 -0
- flock/core/api/ui/routes.py +271 -0
- flock/core/api/ui/utils.py +119 -0
- flock/core/flock.py +509 -388
- flock/core/flock_agent.py +384 -121
- flock/core/flock_registry.py +532 -0
- flock/core/logging/logging.py +97 -23
- flock/core/mixin/dspy_integration.py +363 -158
- flock/core/serialization/__init__.py +7 -1
- flock/core/serialization/callable_registry.py +52 -0
- flock/core/serialization/serializable.py +259 -37
- flock/core/serialization/serialization_utils.py +199 -0
- flock/evaluators/declarative/declarative_evaluator.py +2 -0
- flock/modules/memory/memory_module.py +17 -4
- flock/modules/output/output_module.py +9 -3
- flock/workflow/activities.py +2 -2
- {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/METADATA +6 -3
- {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/RECORD +36 -22
- flock/core/flock_api.py +0 -214
- flock/core/registry/agent_registry.py +0 -120
- {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/WHEEL +0 -0
- {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/entry_points.txt +0 -0
- {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flock-core
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.31
|
|
4
4
|
Summary: Declarative LLM Orchestration at Scale
|
|
5
5
|
Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -12,10 +12,11 @@ Requires-Dist: azure-search-documents>=11.5.2
|
|
|
12
12
|
Requires-Dist: chromadb>=0.6.3
|
|
13
13
|
Requires-Dist: cloudpickle>=3.1.1
|
|
14
14
|
Requires-Dist: devtools>=0.12.2
|
|
15
|
-
Requires-Dist: dspy==2.
|
|
15
|
+
Requires-Dist: dspy==2.6.16
|
|
16
16
|
Requires-Dist: duckduckgo-search>=7.3.2
|
|
17
17
|
Requires-Dist: fastapi>=0.115.8
|
|
18
18
|
Requires-Dist: httpx>=0.28.1
|
|
19
|
+
Requires-Dist: litellm==1.63.7
|
|
19
20
|
Requires-Dist: loguru>=0.7.3
|
|
20
21
|
Requires-Dist: matplotlib>=3.10.0
|
|
21
22
|
Requires-Dist: msgpack>=1.1.0
|
|
@@ -33,6 +34,8 @@ Requires-Dist: pydantic>=2.10.5
|
|
|
33
34
|
Requires-Dist: python-box>=7.3.2
|
|
34
35
|
Requires-Dist: python-decouple>=3.8
|
|
35
36
|
Requires-Dist: python-dotenv>=1.0.1
|
|
37
|
+
Requires-Dist: python-fasthtml>=0.12.6
|
|
38
|
+
Requires-Dist: pyyaml>=6.0
|
|
36
39
|
Requires-Dist: questionary>=2.1.0
|
|
37
40
|
Requires-Dist: rich>=13.9.4
|
|
38
41
|
Requires-Dist: sentence-transformers>=3.4.1
|
|
@@ -59,7 +62,7 @@ Description-Content-Type: text/markdown
|
|
|
59
62
|
|
|
60
63
|
## Overview
|
|
61
64
|
|
|
62
|
-
Flock is a framework for orchestrating LLM-powered agents. It leverages a **declarative approach** where you simply specify what each agent needs as input and what it produces as output
|
|
65
|
+
Flock is a framework for orchestrating LLM-powered agents. It leverages a **declarative approach** where you simply specify what each agent needs as input and what it produces as output, without having to write lengthy, brittle prompts. Under the hood, Flock transforms these declarations into robust workflows, using cutting-edge components such as Temporal and DSPy to handle fault tolerance, state management, and error recovery.
|
|
63
66
|
|
|
64
67
|
|
|
65
68
|
|
|
@@ -1,22 +1,35 @@
|
|
|
1
|
-
flock/__init__.py,sha256=
|
|
1
|
+
flock/__init__.py,sha256=TCFm-Ax0MINIW3-4KdaiGz36raTENp_AY68eO8_a_rQ,2574
|
|
2
2
|
flock/config.py,sha256=O5QJGlStf4DWSK4ovZsKw01ud4YK3_ij6Ay8sWU8ih0,1522
|
|
3
|
-
flock/cli/constants.py,sha256=
|
|
3
|
+
flock/cli/constants.py,sha256=s2Mird8E0QXqPH1xG8gxG7rXYY0F4eftGfbBC5ceG2k,568
|
|
4
4
|
flock/cli/create_agent.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
|
|
5
|
-
flock/cli/create_flock.py,sha256=
|
|
5
|
+
flock/cli/create_flock.py,sha256=Lry15fAwvnh0rHl1pIJ1xKqVj-nYBteNAE1G83LRaAo,6123
|
|
6
|
+
flock/cli/execute_flock.py,sha256=rAP-5nFfyOivi5uWG8mloZwXF9Tj9iD8MYSbllPllQ4,5726
|
|
6
7
|
flock/cli/load_agent.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
|
|
7
8
|
flock/cli/load_examples.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
|
|
8
|
-
flock/cli/load_flock.py,sha256=
|
|
9
|
+
flock/cli/load_flock.py,sha256=5bsdjO5olLtpnFEl_UfisnwR8iSQAkOIWI49tnSwJHc,1537
|
|
9
10
|
flock/cli/load_release_notes.py,sha256=qFcgUrMddAE_TP6x1P-6ZywTUjTknfhTDW5LTxtg1yk,599
|
|
11
|
+
flock/cli/loaded_flock_cli.py,sha256=LXjvTjxt84VG67wBfownICGTbzx0Z2JmCOKAg_L2a6Q,5913
|
|
12
|
+
flock/cli/manage_agents.py,sha256=wkNF0IqNFfePrFueR57SILPW885IPqs3U8Cp-fcPPmo,12710
|
|
10
13
|
flock/cli/settings.py,sha256=Z_TXBzCYlCmSaKrJ_CQCdYy-Cj29gpI4kbC_2KzoKqg,27025
|
|
14
|
+
flock/cli/view_results.py,sha256=dOzK0O1FHSIDERnx48y-2Xke9BkOHS7pcOhs64AyIg0,781
|
|
15
|
+
flock/cli/yaml_editor.py,sha256=VpaSwC-Xcbu_gk4HgUeIL7PXNFu1CdstuJ3mRZOkmIk,8096
|
|
11
16
|
flock/cli/assets/release_notes.md,sha256=bqnk50jxM3w5uY44Dc7MkdT8XmRREFxrVBAG9XCOSSU,4896
|
|
12
|
-
flock/core/__init__.py,sha256=
|
|
13
|
-
flock/core/flock.py,sha256=
|
|
14
|
-
flock/core/flock_agent.py,sha256=
|
|
15
|
-
flock/core/flock_api.py,sha256=2rHnmEdtT5KPZYwGesRT7LqwbrgKClODHT-O56u7pcQ,7140
|
|
17
|
+
flock/core/__init__.py,sha256=6NmSXsdQOoOPWjWqdF8BYiUveb54CjH8Ta0WAjNM0Ps,574
|
|
18
|
+
flock/core/flock.py,sha256=iUHelhSO85qQclHbiJfQzLRepwUFcf3DGBDnrOwgzsM,23722
|
|
19
|
+
flock/core/flock_agent.py,sha256=jkDwB7yVGYyLfg-WuwvR2X4XblXOs5DrB2dB30xBL7Q,24754
|
|
16
20
|
flock/core/flock_evaluator.py,sha256=dOXZeDOGZcAmJ9ahqq_2bdGUU1VOXY4skmwTVpAjiVw,1685
|
|
17
21
|
flock/core/flock_factory.py,sha256=MGTkJCP1WGpV614f87r1vwe0tqAvBCoH9PlqtqDyJDk,2828
|
|
18
22
|
flock/core/flock_module.py,sha256=96aFVYAgwpKN53xGbivQDUpikOYGFCxK5mqhclOcxY0,3003
|
|
23
|
+
flock/core/flock_registry.py,sha256=vQ0N8WSBwOaMLicfmCuFmmOn5ORdF1WhDAJC1BqcHkA,19438
|
|
19
24
|
flock/core/flock_router.py,sha256=A5GaxcGvtiFlRLHBTW7okh5RDm3BdKam2uXvRHRaj7k,2187
|
|
25
|
+
flock/core/api/__init__.py,sha256=OKlhzDWZJfA6ddBwxQUmATY0TSzESsH032u00iVGvdA,228
|
|
26
|
+
flock/core/api/endpoints.py,sha256=m-QAyizCHGh3sd5IXaDEhquSxNgTZLpUVTXLdVjiDVw,9086
|
|
27
|
+
flock/core/api/main.py,sha256=-MJClTcmkyUnaP9fmVu2CcHagFy_9lKk6CAbF05kraY,8928
|
|
28
|
+
flock/core/api/models.py,sha256=mMPCMCD52Txc56_yscwZQG0RRPCJTnIrVKQ8WbI7gts,1111
|
|
29
|
+
flock/core/api/run_store.py,sha256=kmrb0bq2Et5JiSxFWskAAf5a4jTeEFVZShTDlX5jfAk,2773
|
|
30
|
+
flock/core/api/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
+
flock/core/api/ui/routes.py,sha256=nS-wWO94mshE5ozWfOQZ-HOvtes_1qxDVcqpMZtU5JQ,8885
|
|
32
|
+
flock/core/api/ui/utils.py,sha256=V7PqYHNK519hFJ8jvvwf7bGpbBXCRz_HQG3BDCCqlNA,4802
|
|
20
33
|
flock/core/context/context.py,sha256=8bjRLZ74oacRNBaHmDNXdQKfB-95poF7Pp03n2k0zcQ,6437
|
|
21
34
|
flock/core/context/context_manager.py,sha256=FANSWa6DEhdhtZ7t_9Gza0v80UdpoDOhHbfVOccmjkA,1181
|
|
22
35
|
flock/core/context/context_vars.py,sha256=zYTMi9b6mNSSEHowEQUOTpEDurmAjaUcyBCgfKY6-cU,300
|
|
@@ -24,7 +37,7 @@ flock/core/execution/local_executor.py,sha256=rnIQvaJOs6zZORUcR3vvyS6LPREDJTjayg
|
|
|
24
37
|
flock/core/execution/temporal_executor.py,sha256=OF_uXgQsoUGp6U1ZkcuaidAEKyH7XDtbfrtdF10XQ_4,1675
|
|
25
38
|
flock/core/interpreter/python_interpreter.py,sha256=RaUMZuufsKBNQ4FAeSaOgUuxzs8VYu5TgUUs-xwaxxM,26376
|
|
26
39
|
flock/core/logging/__init__.py,sha256=Q8hp9-1ilPIUIV0jLgJ3_cP7COrea32cVwL7dicPnlM,82
|
|
27
|
-
flock/core/logging/logging.py,sha256
|
|
40
|
+
flock/core/logging/logging.py,sha256=-ViLNLTm5wqbvVsc6xYekOsAY38ZCIn6j1wciC7lgeM,15417
|
|
28
41
|
flock/core/logging/telemetry.py,sha256=3E9Tyj6AUR6A5RlIufcdCdWm5BAA7tbOsCa7lHoUQaU,5404
|
|
29
42
|
flock/core/logging/trace_and_logged.py,sha256=5vNrK1kxuPMoPJ0-QjQg-EDJL1oiEzvU6UNi6X8FiMs,2117
|
|
30
43
|
flock/core/logging/formatters/enum_builder.py,sha256=LgEYXUv84wK5vwHflZ5h8HBGgvLH3sByvUQe8tZiyY0,981
|
|
@@ -35,13 +48,14 @@ flock/core/logging/span_middleware/baggage_span_processor.py,sha256=gJfRl8FeB6jd
|
|
|
35
48
|
flock/core/logging/telemetry_exporter/base_exporter.py,sha256=rQJJzS6q9n2aojoSqwCnl7ZtHrh5LZZ-gkxUuI5WfrQ,1124
|
|
36
49
|
flock/core/logging/telemetry_exporter/file_exporter.py,sha256=nKAjJSZtA7FqHSTuTiFtYYepaxOq7l1rDvs8U8rSBlA,3023
|
|
37
50
|
flock/core/logging/telemetry_exporter/sqlite_exporter.py,sha256=CDsiMb9QcqeXelZ6ZqPSS56ovMPGqOu6whzBZRK__Vg,3498
|
|
38
|
-
flock/core/mixin/dspy_integration.py,sha256=
|
|
51
|
+
flock/core/mixin/dspy_integration.py,sha256=vlf6rJnR9EsfZi5KyFLEXIbUvhpBhodctn-mirYo7Pk,17382
|
|
39
52
|
flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
|
|
40
|
-
flock/core/
|
|
41
|
-
flock/core/serialization/
|
|
53
|
+
flock/core/serialization/__init__.py,sha256=CML7fPgG6p4c0CDBlJ_uwV1aZZhJKK9uy3IoIHfO87w,431
|
|
54
|
+
flock/core/serialization/callable_registry.py,sha256=sUZECTZWsM3fJ8FDRQ-FgLNW9hF26nY17AD6fJKADMc,1419
|
|
42
55
|
flock/core/serialization/json_encoder.py,sha256=gAKj2zU_8wQiNvdkby2hksSA4fbPNwTjup_yz1Le1Vw,1229
|
|
43
56
|
flock/core/serialization/secure_serializer.py,sha256=n5-zRvvXddgJv1FFHsaQ2wuYdL3WUSGPvG_LGaffEJo,6144
|
|
44
|
-
flock/core/serialization/serializable.py,sha256=
|
|
57
|
+
flock/core/serialization/serializable.py,sha256=ymuJmm8teLbyUFMakkD7W3a_N8H4igZ1ITQnOqoLt0o,11270
|
|
58
|
+
flock/core/serialization/serialization_utils.py,sha256=YxlPoHFPtj5otWUlKEsKphWxnd_d6b8yMZN_5MDlzB4,7577
|
|
45
59
|
flock/core/tools/azure_tools.py,sha256=9Bi6IrB5pzBTBhBSxpCVMgx8HBud8nl4gDp8aN0NT6c,17031
|
|
46
60
|
flock/core/tools/basic_tools.py,sha256=hEG14jNZ2itVvubCHTfsWkuJK6yuNwBtuFj2Js0VHZs,9043
|
|
47
61
|
flock/core/tools/llm_tools.py,sha256=Bdt4Dpur5dGpxd2KFEQyxjfZazvW1HCDKY6ydMj6UgQ,21811
|
|
@@ -50,17 +64,17 @@ flock/core/tools/dev_tools/github.py,sha256=a2OTPXS7kWOVA4zrZHynQDcsmEi4Pac5MfSj
|
|
|
50
64
|
flock/core/util/cli_helper.py,sha256=QSpP10WRNcjXzVFwpTQA8lSBy7707Qlv7uCit1XjUms,49808
|
|
51
65
|
flock/core/util/hydrator.py,sha256=6qNwOwCZB7r6y25BZ--0PGofrAlfMaXbDKFQeP5NLts,11196
|
|
52
66
|
flock/core/util/input_resolver.py,sha256=g9vDPdY4OH-G7qjas5ksGEHueokHGFPMoLOvC-ngeLo,5984
|
|
53
|
-
flock/evaluators/declarative/declarative_evaluator.py,sha256=
|
|
67
|
+
flock/evaluators/declarative/declarative_evaluator.py,sha256=WZ74LG81JcuApG2KcTk8plh0fFqDhJjtl6ubW1K-fqc,1750
|
|
54
68
|
flock/evaluators/memory/azure_search_evaluator.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
69
|
flock/evaluators/memory/memory_evaluator.py,sha256=SmerXyNaqm8DTV0yw-WqWkn9DXIf6x-nPG1eyTV6NY8,3452
|
|
56
70
|
flock/evaluators/natural_language/natural_language_evaluator.py,sha256=6nVEeh8_uwv_h-d3FWlA0GbzDzRtdhvxCGKirHtyvOU,2012
|
|
57
71
|
flock/evaluators/zep/zep_evaluator.py,sha256=9NOELl7JAuUcx_FQrxY6b-_vN3MjwDyW7ZppPIGeCFc,1954
|
|
58
72
|
flock/modules/azure-search/azure_search_module.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
73
|
flock/modules/callback/callback_module.py,sha256=volGGgHtY19qj1wHR6m5a_hmXSbV3Ca3uY6I76YmcfU,2833
|
|
60
|
-
flock/modules/memory/memory_module.py,sha256=
|
|
74
|
+
flock/modules/memory/memory_module.py,sha256=bSkdFBW-Pp5ldHhXi8v4kfRM7zknfLR2fsOtbTosucI,14916
|
|
61
75
|
flock/modules/memory/memory_parser.py,sha256=FLH7GL8XThvHiCMfX3eQH7Sz-f62fzhAUmO6_gaDI7U,4372
|
|
62
76
|
flock/modules/memory/memory_storage.py,sha256=CNcLDMmvv0x7Z3YMKr6VveS_VCa7rKPw8l2d-XgqokA,27246
|
|
63
|
-
flock/modules/output/output_module.py,sha256=
|
|
77
|
+
flock/modules/output/output_module.py,sha256=wOXMCyldFslj2iCMn2W5VZrSHCauMXwsW7YoFEHEcLY,7846
|
|
64
78
|
flock/modules/performance/metrics_module.py,sha256=UD9OjY4-zAvauMD7YyDYqE1gyIhzpdr3JkBT8j9knxY,16790
|
|
65
79
|
flock/modules/zep/zep_module.py,sha256=x7JG6O6xnwwum0RETIqKYbA3xzdcvX2aUuns0Cl0c2Q,6014
|
|
66
80
|
flock/platform/docker_tools.py,sha256=fpA7-6rJBjPOUBLdQP4ny2QPgJ_042nmqRn5GtKnoYw,1445
|
|
@@ -410,12 +424,12 @@ flock/themes/zenburned.toml,sha256=UEmquBbcAO3Zj652XKUwCsNoC2iQSlIh-q5c6DH-7Kc,1
|
|
|
410
424
|
flock/themes/zenwritten-dark.toml,sha256=To5l6520_3UqAGiEumpzGWsHhXxqu9ThrMildXKgIO0,1669
|
|
411
425
|
flock/themes/zenwritten-light.toml,sha256=G1iEheCPfBNsMTGaVpEVpDzYBHA_T-MV27rolUYolmE,1666
|
|
412
426
|
flock/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
413
|
-
flock/workflow/activities.py,sha256=
|
|
427
|
+
flock/workflow/activities.py,sha256=eVZDnxGJl_quNO-UTV3YgvTV8LrRaHN3QDAA1ANKzac,9065
|
|
414
428
|
flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
|
|
415
429
|
flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
|
|
416
430
|
flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
|
|
417
|
-
flock_core-0.3.
|
|
418
|
-
flock_core-0.3.
|
|
419
|
-
flock_core-0.3.
|
|
420
|
-
flock_core-0.3.
|
|
421
|
-
flock_core-0.3.
|
|
431
|
+
flock_core-0.3.31.dist-info/METADATA,sha256=wWrCmQuj7lyJu1mmgezo7gmkgjwyGh8HC3i-4DyF2xI,20745
|
|
432
|
+
flock_core-0.3.31.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
433
|
+
flock_core-0.3.31.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
|
|
434
|
+
flock_core-0.3.31.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
|
|
435
|
+
flock_core-0.3.31.dist-info/RECORD,,
|
flock/core/flock_api.py
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
"""REST API server for Flock."""
|
|
2
|
-
|
|
3
|
-
import uuid
|
|
4
|
-
from datetime import datetime
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
import uvicorn
|
|
8
|
-
from fastapi import BackgroundTasks, FastAPI, HTTPException
|
|
9
|
-
from pydantic import BaseModel, Field
|
|
10
|
-
|
|
11
|
-
from flock.core.flock import Flock
|
|
12
|
-
from flock.core.logging.logging import get_logger
|
|
13
|
-
|
|
14
|
-
logger = get_logger("api")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class FlockAPIRequest(BaseModel):
|
|
18
|
-
"""Request model for running an agent."""
|
|
19
|
-
|
|
20
|
-
agent_name: str = Field(..., description="Name of the agent to run")
|
|
21
|
-
inputs: dict[str, Any] = Field(
|
|
22
|
-
default_factory=dict, description="Input data for the agent"
|
|
23
|
-
)
|
|
24
|
-
async_run: bool = Field(
|
|
25
|
-
default=False, description="Whether to run asynchronously"
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class FlockAPIResponse(BaseModel):
|
|
30
|
-
"""Response model for run requests."""
|
|
31
|
-
|
|
32
|
-
run_id: str = Field(..., description="Unique ID for this run")
|
|
33
|
-
status: str = Field(..., description="Status of the run")
|
|
34
|
-
result: dict[str, Any] | None = Field(
|
|
35
|
-
None, description="Run result if completed"
|
|
36
|
-
)
|
|
37
|
-
started_at: datetime = Field(..., description="When the run started")
|
|
38
|
-
completed_at: datetime | None = Field(
|
|
39
|
-
None, description="When the run completed"
|
|
40
|
-
)
|
|
41
|
-
error: str | None = Field(None, description="Error message if failed")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class FlockAPI:
|
|
45
|
-
"""REST API server for Flock.
|
|
46
|
-
|
|
47
|
-
Provides HTTP endpoints for:
|
|
48
|
-
- Running agents
|
|
49
|
-
- Checking run status
|
|
50
|
-
- Getting run results
|
|
51
|
-
"""
|
|
52
|
-
|
|
53
|
-
def __init__(self, flock: Flock):
|
|
54
|
-
self.flock = flock
|
|
55
|
-
self.app = FastAPI(title="Flock API")
|
|
56
|
-
self.runs: dict[str, FlockAPIResponse] = {}
|
|
57
|
-
|
|
58
|
-
# Register routes
|
|
59
|
-
self._setup_routes()
|
|
60
|
-
|
|
61
|
-
def _setup_routes(self):
|
|
62
|
-
"""Set up API routes."""
|
|
63
|
-
|
|
64
|
-
@self.app.post("/run/flock", response_model=FlockAPIResponse)
|
|
65
|
-
async def run_flock(
|
|
66
|
-
request: FlockAPIRequest, background_tasks: BackgroundTasks
|
|
67
|
-
):
|
|
68
|
-
"""Run an agent with the provided inputs."""
|
|
69
|
-
try:
|
|
70
|
-
# Generate run ID
|
|
71
|
-
run_id = str(uuid.uuid4())
|
|
72
|
-
|
|
73
|
-
# Create initial response
|
|
74
|
-
response = FlockAPIResponse(
|
|
75
|
-
run_id=run_id, status="starting", started_at=datetime.now()
|
|
76
|
-
)
|
|
77
|
-
self.runs[run_id] = response
|
|
78
|
-
|
|
79
|
-
if request.async_run:
|
|
80
|
-
# Start run in background
|
|
81
|
-
background_tasks.add_task(
|
|
82
|
-
self._run_flock,
|
|
83
|
-
run_id,
|
|
84
|
-
request.agent_name,
|
|
85
|
-
request.inputs,
|
|
86
|
-
)
|
|
87
|
-
response.status = "running"
|
|
88
|
-
else:
|
|
89
|
-
# Run synchronously
|
|
90
|
-
await self._run_flock(
|
|
91
|
-
run_id, request.agent_name, request.inputs
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
return self.runs[run_id]
|
|
95
|
-
|
|
96
|
-
except Exception as e:
|
|
97
|
-
logger.error(f"Error starting run: {e!s}")
|
|
98
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
99
|
-
|
|
100
|
-
@self.app.post("/run/agent", response_model=FlockAPIResponse)
|
|
101
|
-
async def run_agent(
|
|
102
|
-
request: FlockAPIRequest, background_tasks: BackgroundTasks
|
|
103
|
-
):
|
|
104
|
-
"""Run an agent with the provided inputs."""
|
|
105
|
-
try:
|
|
106
|
-
# Generate run ID
|
|
107
|
-
run_id = str(uuid.uuid4())
|
|
108
|
-
|
|
109
|
-
# Create initial response
|
|
110
|
-
response = FlockAPIResponse(
|
|
111
|
-
run_id=run_id, status="starting", started_at=datetime.now()
|
|
112
|
-
)
|
|
113
|
-
self.runs[run_id] = response
|
|
114
|
-
|
|
115
|
-
if request.async_run:
|
|
116
|
-
# Start run in background
|
|
117
|
-
background_tasks.add_task(
|
|
118
|
-
self._run_agent,
|
|
119
|
-
run_id,
|
|
120
|
-
request.agent_name,
|
|
121
|
-
request.inputs,
|
|
122
|
-
)
|
|
123
|
-
response.status = "running"
|
|
124
|
-
else:
|
|
125
|
-
# Run synchronously
|
|
126
|
-
await self._run_agent(
|
|
127
|
-
run_id, request.agent_name, request.inputs
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
return self.runs[run_id]
|
|
131
|
-
|
|
132
|
-
except Exception as e:
|
|
133
|
-
logger.error(f"Error starting run: {e!s}")
|
|
134
|
-
raise HTTPException(status_code=500, detail=str(e))
|
|
135
|
-
|
|
136
|
-
@self.app.get("/run/{run_id}", response_model=FlockAPIResponse)
|
|
137
|
-
async def get_run_status(run_id: str):
|
|
138
|
-
"""Get the status of a run."""
|
|
139
|
-
if run_id not in self.runs:
|
|
140
|
-
raise HTTPException(status_code=404, detail="Run not found")
|
|
141
|
-
return self.runs[run_id]
|
|
142
|
-
|
|
143
|
-
@self.app.get("/agents")
|
|
144
|
-
async def list_agents():
|
|
145
|
-
"""List all available agents."""
|
|
146
|
-
return {
|
|
147
|
-
"agents": [
|
|
148
|
-
{
|
|
149
|
-
"name": agent.name,
|
|
150
|
-
"description": agent.description,
|
|
151
|
-
"input_schema": agent.input,
|
|
152
|
-
"output_schema": agent.output,
|
|
153
|
-
}
|
|
154
|
-
for agent in self.flock.agents.values()
|
|
155
|
-
]
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async def _run_agent(
|
|
159
|
-
self, run_id: str, agent_name: str, inputs: dict[str, Any]
|
|
160
|
-
):
|
|
161
|
-
"""Execute an agent run."""
|
|
162
|
-
try:
|
|
163
|
-
# Get the agent
|
|
164
|
-
if agent_name not in self.flock.agents:
|
|
165
|
-
raise ValueError(f"Agent '{agent_name}' not found")
|
|
166
|
-
|
|
167
|
-
agent = self.flock.agents[agent_name]
|
|
168
|
-
|
|
169
|
-
# Run the agent
|
|
170
|
-
result = await agent.run_async(inputs)
|
|
171
|
-
|
|
172
|
-
# Update run status
|
|
173
|
-
self.runs[run_id].status = "completed"
|
|
174
|
-
self.runs[run_id].result = result
|
|
175
|
-
self.runs[run_id].completed_at = datetime.now()
|
|
176
|
-
|
|
177
|
-
except Exception as e:
|
|
178
|
-
logger.error(f"Error in run {run_id}: {e!s}")
|
|
179
|
-
self.runs[run_id].status = "failed"
|
|
180
|
-
self.runs[run_id].error = str(e)
|
|
181
|
-
self.runs[run_id].completed_at = datetime.now()
|
|
182
|
-
|
|
183
|
-
async def _run_flock(
|
|
184
|
-
self, run_id: str, agent_name: str, inputs: dict[str, Any]
|
|
185
|
-
):
|
|
186
|
-
"""Execute an agent run."""
|
|
187
|
-
try:
|
|
188
|
-
# Get the agent
|
|
189
|
-
if agent_name not in self.flock.agents:
|
|
190
|
-
raise ValueError(f"Agent '{agent_name}' not found")
|
|
191
|
-
|
|
192
|
-
result = await self.flock.run_async(
|
|
193
|
-
start_agent=agent_name, input=inputs
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
# Update run status
|
|
197
|
-
self.runs[run_id].status = "completed"
|
|
198
|
-
self.runs[run_id].result = result
|
|
199
|
-
self.runs[run_id].completed_at = datetime.now()
|
|
200
|
-
|
|
201
|
-
except Exception as e:
|
|
202
|
-
logger.error(f"Error in run {run_id}: {e!s}")
|
|
203
|
-
self.runs[run_id].status = "failed"
|
|
204
|
-
self.runs[run_id].error = str(e)
|
|
205
|
-
self.runs[run_id].completed_at = datetime.now()
|
|
206
|
-
|
|
207
|
-
def start(self, host: str = "0.0.0.0", port: int = 8344):
|
|
208
|
-
"""Start the API server."""
|
|
209
|
-
uvicorn.run(self.app, host=host, port=port)
|
|
210
|
-
|
|
211
|
-
async def stop(self):
|
|
212
|
-
"""Stop the API server."""
|
|
213
|
-
# Cleanup if needed
|
|
214
|
-
pass
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
"""Registry for storing and managing agents and tools with logging and tracing integration."""
|
|
2
|
-
|
|
3
|
-
from collections.abc import Callable
|
|
4
|
-
|
|
5
|
-
from opentelemetry import trace
|
|
6
|
-
|
|
7
|
-
from flock.core.flock_agent import FlockAgent
|
|
8
|
-
from flock.core.flock_module import FlockModule
|
|
9
|
-
from flock.core.logging.logging import get_logger
|
|
10
|
-
|
|
11
|
-
logger = get_logger("registry")
|
|
12
|
-
tracer = trace.get_tracer(__name__)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class Registry:
|
|
16
|
-
"""Registry for storing and managing agents and tools.
|
|
17
|
-
|
|
18
|
-
This singleton class maintains a centralized registry of agents and tools,
|
|
19
|
-
which is particularly important for Temporal workflows where only basic Python
|
|
20
|
-
types can be passed between activities.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
_instance = None
|
|
24
|
-
|
|
25
|
-
def __new__(cls):
|
|
26
|
-
with tracer.start_as_current_span("Registry.__new__") as span:
|
|
27
|
-
if cls._instance is None:
|
|
28
|
-
cls._instance = super().__new__(cls)
|
|
29
|
-
cls._instance._initialize()
|
|
30
|
-
logger.info("Registry instance created")
|
|
31
|
-
span.set_attribute("instance.created", True)
|
|
32
|
-
return cls._instance
|
|
33
|
-
|
|
34
|
-
def _initialize(self):
|
|
35
|
-
with tracer.start_as_current_span("Registry._initialize"):
|
|
36
|
-
self._agents: list[FlockAgent] = []
|
|
37
|
-
self._tools: list[tuple[str, Callable]] = []
|
|
38
|
-
self._modules: list[FlockModule] = []
|
|
39
|
-
logger.info("Registry initialized", agents_count=0, tools_count=0)
|
|
40
|
-
|
|
41
|
-
def register_tool(self, tool_name: str, tool: Callable) -> None:
|
|
42
|
-
with tracer.start_as_current_span("Registry.register_tool") as span:
|
|
43
|
-
span.set_attribute("tool_name", tool_name)
|
|
44
|
-
try:
|
|
45
|
-
self._tools.append((tool_name, tool))
|
|
46
|
-
logger.info("Tool registered", tool_name=tool_name)
|
|
47
|
-
except Exception as e:
|
|
48
|
-
logger.error(
|
|
49
|
-
"Error registering tool", tool_name=tool_name, error=str(e)
|
|
50
|
-
)
|
|
51
|
-
span.record_exception(e)
|
|
52
|
-
raise
|
|
53
|
-
|
|
54
|
-
def register_agent(self, agent: FlockAgent) -> None:
|
|
55
|
-
with tracer.start_as_current_span("Registry.register_agent") as span:
|
|
56
|
-
span.set_attribute("agent_name", agent.name)
|
|
57
|
-
try:
|
|
58
|
-
self._agents.append(agent)
|
|
59
|
-
logger.info("Agent registered", agent=agent.name)
|
|
60
|
-
except Exception as e:
|
|
61
|
-
logger.error(
|
|
62
|
-
"Error registering agent", agent=agent.name, error=str(e)
|
|
63
|
-
)
|
|
64
|
-
span.record_exception(e)
|
|
65
|
-
raise
|
|
66
|
-
|
|
67
|
-
def get_agent(self, name: str) -> FlockAgent | None:
|
|
68
|
-
with tracer.start_as_current_span("Registry.get_agent") as span:
|
|
69
|
-
span.set_attribute("search_agent_name", name)
|
|
70
|
-
try:
|
|
71
|
-
for agent in self._agents:
|
|
72
|
-
if agent.name == name:
|
|
73
|
-
logger.info("Agent found", agent=name)
|
|
74
|
-
span.set_attribute("found", True)
|
|
75
|
-
return agent
|
|
76
|
-
logger.warning("Agent not found", agent=name)
|
|
77
|
-
span.set_attribute("found", False)
|
|
78
|
-
return None
|
|
79
|
-
except Exception as e:
|
|
80
|
-
logger.error("Error retrieving agent", agent=name, error=str(e))
|
|
81
|
-
span.record_exception(e)
|
|
82
|
-
raise
|
|
83
|
-
|
|
84
|
-
def get_tool(self, name: str) -> Callable | None:
|
|
85
|
-
with tracer.start_as_current_span("Registry.get_tool") as span:
|
|
86
|
-
span.set_attribute("search_tool_name", name)
|
|
87
|
-
try:
|
|
88
|
-
for tool_name, tool in self._tools:
|
|
89
|
-
if tool_name == name:
|
|
90
|
-
logger.info("Tool found", tool=name)
|
|
91
|
-
span.set_attribute("found", True)
|
|
92
|
-
return tool
|
|
93
|
-
logger.warning("Tool not found", tool=name)
|
|
94
|
-
span.set_attribute("found", False)
|
|
95
|
-
return None
|
|
96
|
-
except Exception as e:
|
|
97
|
-
logger.error("Error retrieving tool", tool=name, error=str(e))
|
|
98
|
-
span.record_exception(e)
|
|
99
|
-
raise
|
|
100
|
-
|
|
101
|
-
def get_tools(self, names: list[str] | None) -> list[Callable]:
|
|
102
|
-
with tracer.start_as_current_span("Registry.get_tools") as span:
|
|
103
|
-
span.set_attribute("search_tool_names", str(names))
|
|
104
|
-
try:
|
|
105
|
-
if not names:
|
|
106
|
-
logger.info("No tool names provided")
|
|
107
|
-
return []
|
|
108
|
-
tools = [self.get_tool(name) for name in names]
|
|
109
|
-
found_tools = [tool for tool in tools if tool is not None]
|
|
110
|
-
logger.info(
|
|
111
|
-
"Tools retrieved", requested=names, found=len(found_tools)
|
|
112
|
-
)
|
|
113
|
-
span.set_attribute("found_tools_count", len(found_tools))
|
|
114
|
-
return found_tools
|
|
115
|
-
except Exception as e:
|
|
116
|
-
logger.error(
|
|
117
|
-
"Error retrieving tools", names=str(names), error=str(e)
|
|
118
|
-
)
|
|
119
|
-
span.record_exception(e)
|
|
120
|
-
raise
|
|
File without changes
|
|
File without changes
|
|
File without changes
|