fabricatio 0.1.3__tar.gz → 0.2.0.dev1__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.
Files changed (47) hide show
  1. fabricatio-0.2.0.dev1/PKG-INFO +246 -0
  2. fabricatio-0.2.0.dev1/README.md +193 -0
  3. fabricatio-0.2.0.dev1/examples/simple_chat/chat.py +31 -0
  4. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/pyproject.toml +12 -7
  5. fabricatio-0.2.0.dev1/src/fabricatio/actions/__init__.py +5 -0
  6. fabricatio-0.2.0.dev1/src/fabricatio/actions/transmission.py +20 -0
  7. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/config.py +61 -61
  8. fabricatio-0.2.0.dev1/src/fabricatio/decorators.py +56 -0
  9. fabricatio-0.2.0.dev1/src/fabricatio/fs/__init__.py +1 -0
  10. fabricatio-0.2.0.dev1/src/fabricatio/fs/readers.py +5 -0
  11. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/models/action.py +18 -7
  12. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/models/events.py +23 -12
  13. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/models/generic.py +51 -0
  14. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/models/task.py +38 -26
  15. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/parser.py +1 -0
  16. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_core.py +2 -2
  17. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_events.py +10 -10
  18. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_models/test_events.py +5 -5
  19. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/uv.lock +181 -57
  20. fabricatio-0.1.3/PKG-INFO +0 -127
  21. fabricatio-0.1.3/README.md +0 -76
  22. fabricatio-0.1.3/src/fabricatio/actions/__init__.py +0 -5
  23. fabricatio-0.1.3/src/fabricatio/actions/transmission.py +0 -16
  24. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/.github/workflows/build-package.yaml +0 -0
  25. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/.github/workflows/ruff.yaml +0 -0
  26. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/.gitignore +0 -0
  27. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/.python-version +0 -0
  28. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/LICENSE +0 -0
  29. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/examples/minor/hello_fabricatio.py +0 -0
  30. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/__init__.py +0 -0
  31. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/core.py +0 -0
  32. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/journal.py +0 -0
  33. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/models/role.py +0 -0
  34. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/models/tool.py +0 -0
  35. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/models/utils.py +0 -0
  36. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/py.typed +0 -0
  37. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/toolboxes/__init__.py +0 -0
  38. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/src/fabricatio/toolboxes/task.py +0 -0
  39. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/__init__.py +0 -0
  40. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/conftest.py +0 -0
  41. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_config.py +0 -0
  42. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_models/test_action.py +0 -0
  43. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_models/test_generic.py +0 -0
  44. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_models/test_role.py +0 -0
  45. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_models/test_tool.py +0 -0
  46. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_models/test_utils.py +0 -0
  47. {fabricatio-0.1.3 → fabricatio-0.2.0.dev1}/tests/test_parser.py +0 -0
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.4
2
+ Name: fabricatio
3
+ Version: 0.2.0.dev1
4
+ Summary: A LLM multi-agent framework.
5
+ Author-email: Whth <zettainspector@foxmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Whth Yotta
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Keywords: agents,ai,llm,multi-agent
29
+ Classifier: Framework :: AsyncIO
30
+ Classifier: Framework :: Pydantic :: 2
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Programming Language :: Python :: 3.12
33
+ Classifier: Programming Language :: Python :: Implementation :: CPython
34
+ Classifier: Typing :: Typed
35
+ Requires-Python: >=3.12
36
+ Requires-Dist: aiohttp>=3.11.11
37
+ Requires-Dist: aiomultiprocess>=0.9.1
38
+ Requires-Dist: appdirs>=1.4.4
39
+ Requires-Dist: asyncio>=3.4.3
40
+ Requires-Dist: code2prompt
41
+ Requires-Dist: gitpython>=3.1.44
42
+ Requires-Dist: litellm>=1.60.0
43
+ Requires-Dist: loguru>=0.7.3
44
+ Requires-Dist: magika>=0.5.1
45
+ Requires-Dist: orjson>=3.10.15
46
+ Requires-Dist: pydantic-settings>=2.7.1
47
+ Requires-Dist: pydantic>=2.10.6
48
+ Requires-Dist: pymitter>=1.0.0
49
+ Requires-Dist: questionary>=2.1.0
50
+ Requires-Dist: regex>=2024.11.6
51
+ Requires-Dist: rich>=13.9.4
52
+ Description-Content-Type: text/markdown
53
+
54
+ # Fabricatio
55
+
56
+ ---
57
+
58
+ Fabricatio is a powerful framework designed to facilitate the creation and management of tasks, actions, and workflows. It leverages modern Python features and libraries to provide a robust and flexible environment for building applications that require task automation and orchestration.
59
+
60
+ ## Table of Contents
61
+
62
+ - [Installation](#installation)
63
+ - [Usage](#usage)
64
+ - [Defining a Task](#defining-a-task)
65
+ - [Creating an Action](#creating-an-action)
66
+ - [Assigning a Role](#assigning-a-role)
67
+ - [Logging](#logging)
68
+ - [Configuration](#configuration)
69
+ - [LLM Configuration](#llm-configuration)
70
+ - [Debug Configuration](#debug-configuration)
71
+ - [Examples](#examples)
72
+ - [Simple Task Example](#simple-task-example)
73
+ - [Complex Workflow Example](#complex-workflow-example)
74
+ - [Contributing](#contributing)
75
+ - [License](#license)
76
+
77
+ ## Installation
78
+ To install Fabricatio, you can use pip:
79
+
80
+ ```bash
81
+ pip install fabricatio
82
+ ```
83
+
84
+ Alternatively, you can clone the repository and install it manually:
85
+
86
+ ```bash
87
+ git clone https://github.com/your-repo/fabricatio.git
88
+ cd fabricatio
89
+ pip install .
90
+ ```
91
+
92
+
93
+ ## Usage
94
+
95
+ ### Defining a Task
96
+
97
+ A task in Fabricatio is defined using the `Task` class. You can specify the name, goal, and description of the task.
98
+
99
+ ```python
100
+ from fabricatio.models.task import Task
101
+
102
+ task = Task(name="say hello", goal="say hello", description="say hello to the world")
103
+ ```
104
+
105
+
106
+ ### Creating an Action
107
+
108
+ Actions are the building blocks of workflows. They perform specific tasks and can be asynchronous.
109
+
110
+ ```python
111
+ from fabricatio import Action, logger
112
+ from fabricatio.models.task import Task
113
+
114
+ class Talk(Action):
115
+ async def _execute(self, task_input: Task[str], **_) -> str:
116
+ ret = "Hello fabricatio!"
117
+ logger.info("executing talk action")
118
+ return ret
119
+ ```
120
+
121
+
122
+ ### Assigning a Role
123
+
124
+ Roles in Fabricatio are responsible for executing workflows. You can define a role with a set of actions.
125
+
126
+ ```python
127
+ from fabricatio.models.role import Role
128
+ from fabricatio.models.action import WorkFlow
129
+
130
+ class TestWorkflow(WorkFlow):
131
+ pass
132
+
133
+ role = Role(name="Test Role", actions=[TestWorkflow()])
134
+ ```
135
+
136
+
137
+ ### Logging
138
+
139
+ Fabricatio uses Loguru for logging. You can configure the log level and file in the `config.py` file.
140
+
141
+ ```python
142
+ from fabricatio.config import DebugConfig
143
+
144
+ debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
145
+ ```
146
+
147
+
148
+ ## Configuration
149
+
150
+ Fabricatio uses Pydantic for configuration management. You can define your settings in the `config.py` file.
151
+
152
+ ### LLM Configuration
153
+
154
+ The Large Language Model (LLM) configuration is managed by the `LLMConfig` class.
155
+
156
+ ```python
157
+ from fabricatio.config import LLMConfig
158
+
159
+ llm_config = LLMConfig(api_endpoint="https://api.example.com")
160
+ ```
161
+
162
+
163
+ ### Debug Configuration
164
+
165
+ The debug configuration is managed by the `DebugConfig` class.
166
+
167
+ ```python
168
+ from fabricatio.config import DebugConfig
169
+
170
+ debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
171
+ ```
172
+
173
+
174
+ ## Examples
175
+
176
+ ### Simple Task Example
177
+
178
+ Here is a simple example of a task that prints "Hello fabricatio!".
179
+
180
+ ```python
181
+ import asyncio
182
+ from fabricatio import Action, Role, Task, WorkFlow, logger
183
+
184
+ task = Task(name="say hello", goal="say hello", description="say hello to the world")
185
+
186
+ class Talk(Action):
187
+ async def _execute(self, task_input: Task[str], **_) -> Any:
188
+ ret = "Hello fabricatio!"
189
+ logger.info("executing talk action")
190
+ return ret
191
+
192
+ class TestWorkflow(WorkFlow):
193
+ pass
194
+
195
+ role = Role(name="Test Role", actions=[TestWorkflow()])
196
+
197
+ async def main() -> None:
198
+ await role.act(task)
199
+
200
+ if __name__ == "__main__":
201
+ asyncio.run(main())
202
+ ```
203
+
204
+
205
+ ### Complex Workflow Example
206
+
207
+ Here is a more complex example that demonstrates how to create a workflow with multiple actions.
208
+
209
+ ```python
210
+ import asyncio
211
+ from fabricatio import Action, Role, Task, WorkFlow, logger
212
+
213
+ task = Task(name="complex task", goal="perform complex operations", description="a task with multiple actions")
214
+
215
+ class ActionOne(Action):
216
+ async def _execute(self, task_input: Task[str], **_) -> Any:
217
+ ret = "Action One executed"
218
+ logger.info(ret)
219
+ return ret
220
+
221
+ class ActionTwo(Action):
222
+ async def _execute(self, task_input: Task[str], **_) -> Any:
223
+ ret = "Action Two executed"
224
+ logger.info(ret)
225
+ return ret
226
+
227
+ class ComplexWorkflow(WorkFlow):
228
+ actions = [ActionOne(), ActionTwo()]
229
+
230
+ role = Role(name="Complex Role", actions=[ComplexWorkflow()])
231
+
232
+ async def main() -> None:
233
+ await role.act(task)
234
+
235
+ if __name__ == "__main__":
236
+ asyncio.run(main())
237
+ ```
238
+
239
+
240
+ ## Contributing
241
+
242
+ Contributions to Fabricatio are welcome! Please submit a pull request with your changes.
243
+
244
+ ## License
245
+
246
+ Fabricatio is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information.
@@ -0,0 +1,193 @@
1
+ # Fabricatio
2
+
3
+ ---
4
+
5
+ Fabricatio is a powerful framework designed to facilitate the creation and management of tasks, actions, and workflows. It leverages modern Python features and libraries to provide a robust and flexible environment for building applications that require task automation and orchestration.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [Usage](#usage)
11
+ - [Defining a Task](#defining-a-task)
12
+ - [Creating an Action](#creating-an-action)
13
+ - [Assigning a Role](#assigning-a-role)
14
+ - [Logging](#logging)
15
+ - [Configuration](#configuration)
16
+ - [LLM Configuration](#llm-configuration)
17
+ - [Debug Configuration](#debug-configuration)
18
+ - [Examples](#examples)
19
+ - [Simple Task Example](#simple-task-example)
20
+ - [Complex Workflow Example](#complex-workflow-example)
21
+ - [Contributing](#contributing)
22
+ - [License](#license)
23
+
24
+ ## Installation
25
+ To install Fabricatio, you can use pip:
26
+
27
+ ```bash
28
+ pip install fabricatio
29
+ ```
30
+
31
+ Alternatively, you can clone the repository and install it manually:
32
+
33
+ ```bash
34
+ git clone https://github.com/your-repo/fabricatio.git
35
+ cd fabricatio
36
+ pip install .
37
+ ```
38
+
39
+
40
+ ## Usage
41
+
42
+ ### Defining a Task
43
+
44
+ A task in Fabricatio is defined using the `Task` class. You can specify the name, goal, and description of the task.
45
+
46
+ ```python
47
+ from fabricatio.models.task import Task
48
+
49
+ task = Task(name="say hello", goal="say hello", description="say hello to the world")
50
+ ```
51
+
52
+
53
+ ### Creating an Action
54
+
55
+ Actions are the building blocks of workflows. They perform specific tasks and can be asynchronous.
56
+
57
+ ```python
58
+ from fabricatio import Action, logger
59
+ from fabricatio.models.task import Task
60
+
61
+ class Talk(Action):
62
+ async def _execute(self, task_input: Task[str], **_) -> str:
63
+ ret = "Hello fabricatio!"
64
+ logger.info("executing talk action")
65
+ return ret
66
+ ```
67
+
68
+
69
+ ### Assigning a Role
70
+
71
+ Roles in Fabricatio are responsible for executing workflows. You can define a role with a set of actions.
72
+
73
+ ```python
74
+ from fabricatio.models.role import Role
75
+ from fabricatio.models.action import WorkFlow
76
+
77
+ class TestWorkflow(WorkFlow):
78
+ pass
79
+
80
+ role = Role(name="Test Role", actions=[TestWorkflow()])
81
+ ```
82
+
83
+
84
+ ### Logging
85
+
86
+ Fabricatio uses Loguru for logging. You can configure the log level and file in the `config.py` file.
87
+
88
+ ```python
89
+ from fabricatio.config import DebugConfig
90
+
91
+ debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
92
+ ```
93
+
94
+
95
+ ## Configuration
96
+
97
+ Fabricatio uses Pydantic for configuration management. You can define your settings in the `config.py` file.
98
+
99
+ ### LLM Configuration
100
+
101
+ The Large Language Model (LLM) configuration is managed by the `LLMConfig` class.
102
+
103
+ ```python
104
+ from fabricatio.config import LLMConfig
105
+
106
+ llm_config = LLMConfig(api_endpoint="https://api.example.com")
107
+ ```
108
+
109
+
110
+ ### Debug Configuration
111
+
112
+ The debug configuration is managed by the `DebugConfig` class.
113
+
114
+ ```python
115
+ from fabricatio.config import DebugConfig
116
+
117
+ debug_config = DebugConfig(log_level="DEBUG", log_file="fabricatio.log")
118
+ ```
119
+
120
+
121
+ ## Examples
122
+
123
+ ### Simple Task Example
124
+
125
+ Here is a simple example of a task that prints "Hello fabricatio!".
126
+
127
+ ```python
128
+ import asyncio
129
+ from fabricatio import Action, Role, Task, WorkFlow, logger
130
+
131
+ task = Task(name="say hello", goal="say hello", description="say hello to the world")
132
+
133
+ class Talk(Action):
134
+ async def _execute(self, task_input: Task[str], **_) -> Any:
135
+ ret = "Hello fabricatio!"
136
+ logger.info("executing talk action")
137
+ return ret
138
+
139
+ class TestWorkflow(WorkFlow):
140
+ pass
141
+
142
+ role = Role(name="Test Role", actions=[TestWorkflow()])
143
+
144
+ async def main() -> None:
145
+ await role.act(task)
146
+
147
+ if __name__ == "__main__":
148
+ asyncio.run(main())
149
+ ```
150
+
151
+
152
+ ### Complex Workflow Example
153
+
154
+ Here is a more complex example that demonstrates how to create a workflow with multiple actions.
155
+
156
+ ```python
157
+ import asyncio
158
+ from fabricatio import Action, Role, Task, WorkFlow, logger
159
+
160
+ task = Task(name="complex task", goal="perform complex operations", description="a task with multiple actions")
161
+
162
+ class ActionOne(Action):
163
+ async def _execute(self, task_input: Task[str], **_) -> Any:
164
+ ret = "Action One executed"
165
+ logger.info(ret)
166
+ return ret
167
+
168
+ class ActionTwo(Action):
169
+ async def _execute(self, task_input: Task[str], **_) -> Any:
170
+ ret = "Action Two executed"
171
+ logger.info(ret)
172
+ return ret
173
+
174
+ class ComplexWorkflow(WorkFlow):
175
+ actions = [ActionOne(), ActionTwo()]
176
+
177
+ role = Role(name="Complex Role", actions=[ComplexWorkflow()])
178
+
179
+ async def main() -> None:
180
+ await role.act(task)
181
+
182
+ if __name__ == "__main__":
183
+ asyncio.run(main())
184
+ ```
185
+
186
+
187
+ ## Contributing
188
+
189
+ Contributions to Fabricatio are welcome! Please submit a pull request with your changes.
190
+
191
+ ## License
192
+
193
+ Fabricatio is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information.
@@ -0,0 +1,31 @@
1
+ import asyncio
2
+ from typing import Any
3
+
4
+ from fabricatio import Action, Role, Task, WorkFlow, logger
5
+
6
+ task = Task(name="say hello", goal="say hello", description="say hello to the world")
7
+
8
+
9
+ class Talk(Action):
10
+ """Action that says hello to the world."""
11
+
12
+ name: str = "talk"
13
+ output_key: str = "task_output"
14
+
15
+ async def _execute(self, task_input: Task[str], **_) -> Any:
16
+ ret = "Hello fabricatio!"
17
+ logger.info("executing talk action")
18
+ return ret
19
+
20
+
21
+ async def main() -> None:
22
+ """Main function."""
23
+ role = Role(
24
+ name="talker", description="talker role", registry={task.pending_label: WorkFlow(name="talk", steps=(Talk,))}
25
+ )
26
+ logger.info(Task.json_example())
27
+ logger.info(f"proposed task: {await role.propose('say hello to Jhon')}")
28
+
29
+
30
+ if __name__ == "__main__":
31
+ asyncio.run(main())
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fabricatio"
3
- version = "0.1.3"
3
+ version = "0.2.0-dev.1"
4
4
  description = "A LLM multi-agent framework."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -27,16 +27,18 @@ dependencies = [
27
27
  "aiomultiprocess>=0.9.1",
28
28
  "appdirs>=1.4.4",
29
29
  "asyncio>=3.4.3",
30
+ "code2prompt",
30
31
  "gitpython>=3.1.44",
31
32
  "litellm>=1.60.0",
32
33
  "loguru>=0.7.3",
34
+ "magika>=0.5.1",
33
35
  "orjson>=3.10.15",
34
36
  "pydantic>=2.10.6",
35
37
  "pydantic-settings>=2.7.1",
36
38
  "pymitter>=1.0.0",
39
+ "questionary>=2.1.0",
37
40
  "regex>=2024.11.6",
38
41
  "rich>=13.9.4",
39
- "shutilwhich>=1.1.0",
40
42
  ]
41
43
 
42
44
 
@@ -123,16 +125,19 @@ testpaths = [
123
125
  "tests",
124
126
  ]
125
127
 
128
+ [tool.uv.sources]
129
+ code2prompt = { git = "https://github.com/mufeedvh/code2prompt" }
126
130
 
127
131
  [[tool.uv.index]]
128
- url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
132
+ url = "https://mirrors.bfsu.edu.cn/pypi/web/simple"
133
+ default = true
129
134
 
130
135
  [[tool.uv.index]]
131
- url = "https://mirrors.huaweicloud.com/repository/pypi/simple"
136
+ url = "https://mirrors.aliyun.com/pypi/simple/"
132
137
 
133
138
  [[tool.uv.index]]
134
- url = "https://mirrors.aliyun.com/pypi/simple/"
139
+ url = "https://mirrors.huaweicloud.com/repository/pypi/simple"
135
140
 
136
141
  [[tool.uv.index]]
137
- url = "https://mirrors.bfsu.edu.cn/pypi/web/simple"
138
- default = true
142
+ url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
143
+
@@ -0,0 +1,5 @@
1
+ """module for actions."""
2
+
3
+ from fabricatio.actions.transmission import PublishTask
4
+
5
+ __all__ = ["PublishTask"]
@@ -0,0 +1,20 @@
1
+ from typing import List
2
+
3
+ from fabricatio.journal import logger
4
+ from fabricatio.models.action import Action
5
+ from fabricatio.models.events import EventLike
6
+ from fabricatio.models.task import Task
7
+
8
+
9
+ class PublishTask(Action):
10
+ """An action that publishes a task to a list of targets."""
11
+
12
+ name: str = "publish_task"
13
+ """The name of the action."""
14
+ description: str = "Publish a task to a list of targets."
15
+
16
+ async def _execute(self, send_targets: List[EventLike], send_task: Task, **_) -> None:
17
+ """Execute the action by sending the task to the specified targets."""
18
+ logger.info(f"Sending task {send_task.name} to {send_targets}")
19
+ for target in send_targets:
20
+ await send_task.move_to(target).publish()