fabricatio 0.2.0.dev19__cp312-cp312-win_amd64.whl → 0.2.1__cp312-cp312-win_amd64.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.
- fabricatio/_rust.cp312-win_amd64.pyd +0 -0
- fabricatio/_rust.pyi +3 -3
- fabricatio/actions/communication.py +6 -6
- fabricatio/actions/transmission.py +0 -11
- fabricatio/config.py +18 -3
- fabricatio/decorators.py +118 -11
- fabricatio/fs/curd.py +21 -7
- fabricatio/journal.py +7 -2
- fabricatio/models/action.py +9 -3
- fabricatio/models/advanced.py +23 -14
- fabricatio/models/generic.py +23 -2
- fabricatio/models/role.py +1 -2
- fabricatio/models/task.py +16 -10
- fabricatio/models/tool.py +25 -9
- fabricatio/models/usages.py +72 -17
- fabricatio/parser.py +8 -4
- fabricatio/toolboxes/fs.py +3 -2
- fabricatio-0.2.1.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.1.dist-info/METADATA +420 -0
- fabricatio-0.2.1.dist-info/RECORD +35 -0
- fabricatio-0.2.0.dev19.data/scripts/tdown.exe +0 -0
- fabricatio-0.2.0.dev19.dist-info/METADATA +0 -233
- fabricatio-0.2.0.dev19.dist-info/RECORD +0 -35
- {fabricatio-0.2.0.dev19.dist-info → fabricatio-0.2.1.dist-info}/WHEEL +0 -0
- {fabricatio-0.2.0.dev19.dist-info → fabricatio-0.2.1.dist-info}/licenses/LICENSE +0 -0
Binary file
|
fabricatio/_rust.pyi
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from pathlib import Path
|
2
|
-
from typing import Dict, List, Optional
|
2
|
+
from typing import Any, Dict, List, Optional
|
3
3
|
|
4
4
|
class TemplateManager:
|
5
5
|
"""TemplateManager class for managing handlebars templates."""
|
@@ -31,12 +31,12 @@ class TemplateManager:
|
|
31
31
|
def discover_templates(self) -> None:
|
32
32
|
"""Discover templates in the specified directories."""
|
33
33
|
|
34
|
-
def render_template(self, name: str, data: Dict[str,
|
34
|
+
def render_template(self, name: str, data: Dict[str, Any]) -> str:
|
35
35
|
"""Render a template with the given name and data.
|
36
36
|
|
37
37
|
Args:
|
38
38
|
name (str): The name of the template to render.
|
39
|
-
data (Dict[str,
|
39
|
+
data (Dict[str, Any]): The data to pass to the template.
|
40
40
|
|
41
41
|
Returns:
|
42
42
|
str: The rendered template.
|
@@ -4,12 +4,12 @@ from fabricatio.models.action import Action
|
|
4
4
|
from fabricatio.models.task import Task
|
5
5
|
|
6
6
|
|
7
|
-
class
|
8
|
-
"""Action that
|
7
|
+
class Examining(Action):
|
8
|
+
"""Action that examines the input data."""
|
9
9
|
|
10
10
|
name: str = "talk"
|
11
|
-
output_key: str = "
|
11
|
+
output_key: str = "examine_pass"
|
12
12
|
|
13
|
-
async def _execute(self,
|
14
|
-
"""
|
15
|
-
|
13
|
+
async def _execute(self, exam_target: Task[str], to_examine: str, **_) -> bool:
|
14
|
+
"""Examine the input data."""
|
15
|
+
# TODO
|
@@ -21,14 +21,3 @@ class PublishTask(Action):
|
|
21
21
|
logger.info(f"Sending task {send_task.name} to {send_targets}")
|
22
22
|
for target in send_targets:
|
23
23
|
await send_task.move_to(target).publish()
|
24
|
-
|
25
|
-
|
26
|
-
class CycleTask(Action):
|
27
|
-
"""An action that cycles a task through a list of targets."""
|
28
|
-
|
29
|
-
name: str = "cycle_task"
|
30
|
-
"""The name of the action."""
|
31
|
-
description: str = "Cycle a task through a list of targets"
|
32
|
-
|
33
|
-
async def _execute(self, task_input: Task, **_) -> None:
|
34
|
-
"""Execute the action by cycling the task through the specified targets."""
|
fabricatio/config.py
CHANGED
@@ -89,7 +89,7 @@ class PymitterConfig(BaseModel):
|
|
89
89
|
"""
|
90
90
|
|
91
91
|
model_config = ConfigDict(use_attribute_docstrings=True)
|
92
|
-
delimiter: str = Field(default="
|
92
|
+
delimiter: str = Field(default="::", frozen=True)
|
93
93
|
"""The delimiter used to separate the event name into segments."""
|
94
94
|
|
95
95
|
new_listener_event: bool = Field(default=False, frozen=True)
|
@@ -115,6 +115,15 @@ class DebugConfig(BaseModel):
|
|
115
115
|
log_file: FilePath = Field(default=rf"{ROAMING_DIR}\fabricatio.log")
|
116
116
|
"""The log file of the application."""
|
117
117
|
|
118
|
+
rotation: int = Field(default=1)
|
119
|
+
"""The rotation of the log file. in weeks."""
|
120
|
+
|
121
|
+
retention: int = Field(default=2)
|
122
|
+
"""The retention of the log file. in weeks."""
|
123
|
+
|
124
|
+
streaming_visible: bool = Field(default=False)
|
125
|
+
"""Whether to print the llm output when streaming."""
|
126
|
+
|
118
127
|
|
119
128
|
class TemplateConfig(BaseModel):
|
120
129
|
"""Template configuration class."""
|
@@ -145,6 +154,9 @@ class TemplateConfig(BaseModel):
|
|
145
154
|
dependencies_template: str = Field(default="dependencies")
|
146
155
|
"""The name of the dependencies template which will be used to manage dependencies."""
|
147
156
|
|
157
|
+
task_briefing_template: str = Field(default="task_briefing")
|
158
|
+
"""The name of the task briefing template which will be used to brief a task."""
|
159
|
+
|
148
160
|
|
149
161
|
class MagikaConfig(BaseModel):
|
150
162
|
"""Magika configuration class."""
|
@@ -161,8 +173,8 @@ class GeneralConfig(BaseModel):
|
|
161
173
|
workspace: DirectoryPath = Field(default=DirectoryPath(r"."))
|
162
174
|
"""The workspace directory for the application."""
|
163
175
|
|
164
|
-
|
165
|
-
"""Whether to confirm on
|
176
|
+
confirm_on_ops: bool = Field(default=True)
|
177
|
+
"""Whether to confirm on operations."""
|
166
178
|
|
167
179
|
|
168
180
|
class ToolBoxConfig(BaseModel):
|
@@ -173,6 +185,9 @@ class ToolBoxConfig(BaseModel):
|
|
173
185
|
tool_module_name: str = Field(default="Toolbox")
|
174
186
|
"""The name of the module containing the toolbox."""
|
175
187
|
|
188
|
+
data_module_name: str = Field(default="Data")
|
189
|
+
"""The name of the module containing the data."""
|
190
|
+
|
176
191
|
|
177
192
|
class Settings(BaseSettings):
|
178
193
|
"""Application settings class.
|
fabricatio/decorators.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
"""Decorators for Fabricatio."""
|
2
2
|
|
3
|
+
from asyncio import iscoroutinefunction
|
3
4
|
from functools import wraps
|
4
5
|
from inspect import signature
|
5
6
|
from shutil import which
|
6
|
-
from
|
7
|
+
from types import ModuleType
|
8
|
+
from typing import Callable, List, Optional
|
7
9
|
|
8
10
|
from questionary import confirm
|
9
11
|
|
@@ -46,6 +48,25 @@ def depend_on_external_cmd[**P, R](
|
|
46
48
|
return _decorator
|
47
49
|
|
48
50
|
|
51
|
+
def logging_execution_info[**P, R](func: Callable[P, R]) -> Callable[P, R]:
|
52
|
+
"""Decorator to log the execution of a function.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
func (Callable): The function to be executed
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
Callable: A decorator that wraps the function to log the execution.
|
59
|
+
"""
|
60
|
+
|
61
|
+
@wraps(func)
|
62
|
+
def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
63
|
+
logger.info(f"Executing function: {func.__name__}{signature(func)}")
|
64
|
+
logger.debug(f"{func.__name__}{signature(func)}\nArgs: {args}\nKwargs: {kwargs}")
|
65
|
+
return func(*args, **kwargs)
|
66
|
+
|
67
|
+
return _wrapper
|
68
|
+
|
69
|
+
|
49
70
|
def confirm_to_execute[**P, R](func: Callable[P, R]) -> Callable[P, Optional[R]] | Callable[P, R]:
|
50
71
|
"""Decorator to confirm before executing a function.
|
51
72
|
|
@@ -55,18 +76,104 @@ def confirm_to_execute[**P, R](func: Callable[P, R]) -> Callable[P, Optional[R]]
|
|
55
76
|
Returns:
|
56
77
|
Callable: A decorator that wraps the function to confirm before execution.
|
57
78
|
"""
|
58
|
-
if not configs.general.
|
79
|
+
if not configs.general.confirm_on_ops:
|
59
80
|
# Skip confirmation if the configuration is set to False
|
60
81
|
return func
|
61
82
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
83
|
+
if iscoroutinefunction(func):
|
84
|
+
|
85
|
+
@wraps(func)
|
86
|
+
async def _wrapper(*args: P.args, **kwargs: P.kwargs) -> Optional[R]:
|
87
|
+
if await confirm(
|
88
|
+
f"Are you sure to execute function: {func.__name__}{signature(func)} \n📦 Args:{args}\n🔑 Kwargs:{kwargs}\n",
|
89
|
+
instruction="Please input [Yes/No] to proceed (default: Yes):",
|
90
|
+
).ask_async():
|
91
|
+
return await func(*args, **kwargs)
|
92
|
+
logger.warning(f"Function: {func.__name__}{signature(func)} canceled by user.")
|
93
|
+
return None
|
94
|
+
|
95
|
+
else:
|
96
|
+
|
97
|
+
@wraps(func)
|
98
|
+
def _wrapper(*args: P.args, **kwargs: P.kwargs) -> Optional[R]:
|
99
|
+
if confirm(
|
100
|
+
f"Are you sure to execute function: {func.__name__}{signature(func)} \n📦 Args:{args}\n��� Kwargs:{kwargs}\n",
|
101
|
+
instruction="Please input [Yes/No] to proceed (default: Yes):",
|
102
|
+
).ask():
|
103
|
+
return func(*args, **kwargs)
|
104
|
+
logger.warning(f"Function: {func.__name__}{signature(func)} canceled by user.")
|
105
|
+
return None
|
71
106
|
|
72
107
|
return _wrapper
|
108
|
+
|
109
|
+
|
110
|
+
def use_temp_module[**P, R](modules: ModuleType | List[ModuleType]) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
111
|
+
"""Temporarily inject modules into sys.modules during function execution.
|
112
|
+
|
113
|
+
This decorator allows you to temporarily inject one or more modules into sys.modules
|
114
|
+
while the decorated function executes. After execution, it restores the original
|
115
|
+
state of sys.modules.
|
116
|
+
|
117
|
+
Args:
|
118
|
+
modules (ModuleType | List[ModuleType]): A single module or list of modules to
|
119
|
+
temporarily inject into sys.modules.
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
Callable[[Callable[P, R]], Callable[P, R]]: A decorator that handles temporary
|
123
|
+
module injection.
|
124
|
+
|
125
|
+
Examples:
|
126
|
+
```python
|
127
|
+
from types import ModuleSpec, ModuleType, module_from_spec
|
128
|
+
|
129
|
+
# Create a temporary module
|
130
|
+
temp_module = module_from_spec(ModuleSpec("temp_math", None))
|
131
|
+
temp_module.pi = 3.14
|
132
|
+
|
133
|
+
# Use the decorator to temporarily inject the module
|
134
|
+
@use_temp_module(temp_module)
|
135
|
+
def calculate_area(radius: float) -> float:
|
136
|
+
from temp_math import pi
|
137
|
+
return pi * radius ** 2
|
138
|
+
|
139
|
+
# The temp_module is only available inside the function
|
140
|
+
result = calculate_area(5.0) # Uses temp_module.pi
|
141
|
+
```
|
142
|
+
|
143
|
+
Multiple modules can also be injected:
|
144
|
+
```python
|
145
|
+
module1 = module_from_spec(ModuleSpec("mod1", None))
|
146
|
+
module2 = module_from_spec(ModuleSpec("mod2", None))
|
147
|
+
|
148
|
+
@use_temp_module([module1, module2])
|
149
|
+
def process_data():
|
150
|
+
import mod1, mod2
|
151
|
+
# Work with temporary modules
|
152
|
+
...
|
153
|
+
```
|
154
|
+
"""
|
155
|
+
module_list = [modules] if isinstance(modules, ModuleType) else modules
|
156
|
+
|
157
|
+
def _decorator(func: Callable[P, R]) -> Callable[P, R]:
|
158
|
+
@wraps(func)
|
159
|
+
def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
160
|
+
import sys
|
161
|
+
|
162
|
+
# Store original modules if they exist
|
163
|
+
for module in module_list:
|
164
|
+
if module.__name__ in sys.modules:
|
165
|
+
raise RuntimeError(
|
166
|
+
f"Module '{module.__name__}' is already present in sys.modules and cannot be overridden."
|
167
|
+
)
|
168
|
+
sys.modules[module.__name__] = module
|
169
|
+
|
170
|
+
try:
|
171
|
+
return func(*args, **kwargs)
|
172
|
+
finally:
|
173
|
+
# Restore original state
|
174
|
+
for module in module_list:
|
175
|
+
del sys.modules[module.__name__]
|
176
|
+
|
177
|
+
return _wrapper
|
178
|
+
|
179
|
+
return _decorator
|
fabricatio/fs/curd.py
CHANGED
@@ -5,11 +5,25 @@ import subprocess
|
|
5
5
|
from pathlib import Path
|
6
6
|
from typing import Union
|
7
7
|
|
8
|
-
from fabricatio.decorators import
|
8
|
+
from fabricatio.decorators import depend_on_external_cmd, logging_execution_info
|
9
9
|
from fabricatio.journal import logger
|
10
10
|
|
11
11
|
|
12
|
-
@
|
12
|
+
@logging_execution_info
|
13
|
+
def dump_text(path: Union[str, Path], text: str) -> None:
|
14
|
+
"""Dump text to a file. you need to make sure the file's parent directory exists.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
path(str, Path): Path to the file
|
18
|
+
text(str): Text to write to the file
|
19
|
+
|
20
|
+
Returns:
|
21
|
+
None
|
22
|
+
"""
|
23
|
+
Path(path).write_text(text, encoding="utf-8", errors="ignore")
|
24
|
+
|
25
|
+
|
26
|
+
@logging_execution_info
|
13
27
|
def copy_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
14
28
|
"""Copy a file from source to destination.
|
15
29
|
|
@@ -29,7 +43,7 @@ def copy_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
|
29
43
|
raise
|
30
44
|
|
31
45
|
|
32
|
-
@
|
46
|
+
@logging_execution_info
|
33
47
|
def move_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
34
48
|
"""Move a file from source to destination.
|
35
49
|
|
@@ -49,7 +63,7 @@ def move_file(src: Union[str, Path], dst: Union[str, Path]) -> None:
|
|
49
63
|
raise
|
50
64
|
|
51
65
|
|
52
|
-
@
|
66
|
+
@logging_execution_info
|
53
67
|
def delete_file(file_path: Union[str, Path]) -> None:
|
54
68
|
"""Delete a file.
|
55
69
|
|
@@ -68,7 +82,7 @@ def delete_file(file_path: Union[str, Path]) -> None:
|
|
68
82
|
raise
|
69
83
|
|
70
84
|
|
71
|
-
@
|
85
|
+
@logging_execution_info
|
72
86
|
def create_directory(dir_path: Union[str, Path], parents: bool = True, exist_ok: bool = True) -> None:
|
73
87
|
"""Create a directory.
|
74
88
|
|
@@ -85,7 +99,7 @@ def create_directory(dir_path: Union[str, Path], parents: bool = True, exist_ok:
|
|
85
99
|
raise
|
86
100
|
|
87
101
|
|
88
|
-
@
|
102
|
+
@logging_execution_info
|
89
103
|
@depend_on_external_cmd(
|
90
104
|
"erd",
|
91
105
|
"Please install `erd` using `cargo install erdtree` or `scoop install erdtree`.",
|
@@ -97,7 +111,7 @@ def tree(dir_path: Union[str, Path]) -> str:
|
|
97
111
|
return subprocess.check_output(("erd", dir_path.as_posix()), encoding="utf-8") # noqa: S603
|
98
112
|
|
99
113
|
|
100
|
-
@
|
114
|
+
@logging_execution_info
|
101
115
|
def delete_directory(dir_path: Union[str, Path]) -> None:
|
102
116
|
"""Delete a directory and its contents.
|
103
117
|
|
fabricatio/journal.py
CHANGED
@@ -3,17 +3,22 @@
|
|
3
3
|
import sys
|
4
4
|
|
5
5
|
from loguru import logger
|
6
|
-
from rich import traceback
|
6
|
+
from rich import pretty, traceback
|
7
7
|
|
8
8
|
from fabricatio.config import configs
|
9
9
|
|
10
|
+
pretty.install()
|
10
11
|
traceback.install()
|
11
12
|
logger.remove()
|
12
13
|
logger.add(
|
13
|
-
configs.debug.log_file,
|
14
|
+
configs.debug.log_file,
|
15
|
+
level=configs.debug.log_level,
|
16
|
+
rotation=f"{configs.debug.rotation} weeks",
|
17
|
+
retention=f"{configs.debug.retention} weeks",
|
14
18
|
)
|
15
19
|
logger.add(sys.stderr, level=configs.debug.log_level)
|
16
20
|
|
21
|
+
|
17
22
|
if __name__ == "__main__":
|
18
23
|
logger.debug("This is a trace message.")
|
19
24
|
logger.info("This is an information message.")
|
fabricatio/models/action.py
CHANGED
@@ -52,7 +52,7 @@ class Action(HandleTask, ProposeTask):
|
|
52
52
|
return f"# The action you are going to perform: \n{super().briefing}"
|
53
53
|
|
54
54
|
|
55
|
-
class WorkFlow
|
55
|
+
class WorkFlow(WithBriefing, ToolBoxUsage):
|
56
56
|
"""Class that represents a workflow to be executed in a task."""
|
57
57
|
|
58
58
|
_context: Queue[Dict[str, Any]] = PrivateAttr(default_factory=lambda: Queue(maxsize=1))
|
@@ -61,7 +61,7 @@ class WorkFlow[A: Union[Type[Action], Action]](WithBriefing, ToolBoxUsage):
|
|
61
61
|
_instances: Tuple[Action, ...] = PrivateAttr(...)
|
62
62
|
""" The instances of the workflow steps."""
|
63
63
|
|
64
|
-
steps: Tuple[
|
64
|
+
steps: Tuple[Union[Type[Action], Action], ...] = Field(...)
|
65
65
|
""" The steps to be executed in the workflow, actions or action classes."""
|
66
66
|
task_input_key: str = Field(default="task_input")
|
67
67
|
""" The key of the task input data."""
|
@@ -111,7 +111,13 @@ class WorkFlow[A: Union[Type[Action], Action]](WithBriefing, ToolBoxUsage):
|
|
111
111
|
await self._context.put(modified_ctx)
|
112
112
|
current_action = step.name
|
113
113
|
logger.info(f"Finished executing workflow: {self.name}")
|
114
|
-
|
114
|
+
final_ctx = await self._context.get()
|
115
|
+
if self.task_output_key not in final_ctx:
|
116
|
+
logger.warning(
|
117
|
+
f"Task output key: {self.task_output_key} not found in the context, None will be returned. You can check if `Action.output_key` is set the same as `WorkFlow.task_output_key`."
|
118
|
+
)
|
119
|
+
|
120
|
+
await task.finish(final_ctx.get(self.task_output_key, None))
|
115
121
|
except RuntimeError as e:
|
116
122
|
logger.error(f"Error during task: {current_action} execution: {e}") # Log the exception
|
117
123
|
logger.error(traceback.format_exc()) # Add this line to log the traceback
|
fabricatio/models/advanced.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
"""A module for advanced models and functionalities."""
|
2
2
|
|
3
3
|
from types import CodeType
|
4
|
-
from typing import List, Optional, Tuple, Unpack
|
4
|
+
from typing import Any, Dict, List, Optional, Tuple, Unpack
|
5
5
|
|
6
6
|
import orjson
|
7
7
|
from fabricatio._rust_instances import template_manager
|
@@ -67,6 +67,7 @@ class HandleTask(WithBriefing, ToolBoxUsage):
|
|
67
67
|
self,
|
68
68
|
task: Task,
|
69
69
|
tools: List[Tool],
|
70
|
+
data: Dict[str, Any],
|
70
71
|
**kwargs: Unpack[LLMKwargs],
|
71
72
|
) -> Tuple[CodeType, List[str]]:
|
72
73
|
"""Asynchronously drafts the tool usage code for a task based on a given task object and tools."""
|
@@ -82,17 +83,23 @@ class HandleTask(WithBriefing, ToolBoxUsage):
|
|
82
83
|
to_extract := JsonCapture.convert_with(response, orjson.loads)
|
83
84
|
):
|
84
85
|
return source, to_extract
|
86
|
+
|
85
87
|
return None
|
86
88
|
|
89
|
+
q = template_manager.render_template(
|
90
|
+
configs.templates.draft_tool_usage_code_template,
|
91
|
+
{
|
92
|
+
"data_module_name": configs.toolbox.data_module_name,
|
93
|
+
"tool_module_name": configs.toolbox.tool_module_name,
|
94
|
+
"task": task.briefing,
|
95
|
+
"deps": task.dependencies_prompt,
|
96
|
+
"tools": [{"name": t.name, "briefing": t.briefing} for t in tools],
|
97
|
+
"data": data,
|
98
|
+
},
|
99
|
+
)
|
100
|
+
logger.debug(f"Code Drafting Question: \n{q}")
|
87
101
|
return await self.aask_validate(
|
88
|
-
question=
|
89
|
-
configs.templates.draft_tool_usage_code_template,
|
90
|
-
{
|
91
|
-
"tool_module_name": configs.toolbox.tool_module_name,
|
92
|
-
"task": task.briefing,
|
93
|
-
"tools": [tool.briefing for tool in tools],
|
94
|
-
},
|
95
|
-
),
|
102
|
+
question=q,
|
96
103
|
validator=_validator,
|
97
104
|
system_message=f"# your personal briefing: \n{self.briefing}",
|
98
105
|
**kwargs,
|
@@ -101,18 +108,20 @@ class HandleTask(WithBriefing, ToolBoxUsage):
|
|
101
108
|
async def handle_fin_grind(
|
102
109
|
self,
|
103
110
|
task: Task,
|
111
|
+
data: Dict[str, Any],
|
104
112
|
**kwargs: Unpack[LLMKwargs],
|
105
113
|
) -> Optional[Tuple]:
|
106
114
|
"""Asynchronously handles a task based on a given task object and parameters."""
|
107
|
-
logger.info(f"Handling task: {task.briefing}")
|
115
|
+
logger.info(f"Handling task: \n{task.briefing}")
|
108
116
|
|
109
117
|
tools = await self.gather_tools(task)
|
110
|
-
logger.info(f"{self.name} have gathered {
|
118
|
+
logger.info(f"{self.name} have gathered {[t.name for t in tools]}")
|
111
119
|
|
112
120
|
if tools:
|
113
|
-
executor = ToolExecutor(
|
114
|
-
code, to_extract = await self.draft_tool_usage_code(task, tools, **kwargs)
|
115
|
-
|
121
|
+
executor = ToolExecutor(candidates=tools, data=data)
|
122
|
+
code, to_extract = await self.draft_tool_usage_code(task, tools, data, **kwargs)
|
123
|
+
|
124
|
+
cxt = executor.execute(code)
|
116
125
|
if to_extract:
|
117
126
|
return tuple(cxt.get(k) for k in to_extract)
|
118
127
|
|
fabricatio/models/generic.py
CHANGED
@@ -68,7 +68,7 @@ class WithDependency(Base):
|
|
68
68
|
"""Class that manages file dependencies."""
|
69
69
|
|
70
70
|
dependencies: List[str] = Field(default_factory=list)
|
71
|
-
"""The file dependencies
|
71
|
+
"""The file dependencies which is needed to read or write to meet a specific requirement, a list of file paths."""
|
72
72
|
|
73
73
|
def add_dependency[P: str | Path](self, dependency: P | List[P]) -> Self:
|
74
74
|
"""Add a file dependency to the task.
|
@@ -99,6 +99,26 @@ class WithDependency(Base):
|
|
99
99
|
self.dependencies.remove(Path(d).as_posix())
|
100
100
|
return self
|
101
101
|
|
102
|
+
def clear_dependencies(self) -> Self:
|
103
|
+
"""Clear all file dependencies from the task.
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
Self: The current instance of the task.
|
107
|
+
"""
|
108
|
+
self.dependencies.clear()
|
109
|
+
return self
|
110
|
+
|
111
|
+
def override_dependencies[P: str | Path](self, dependencies: List[P]) -> Self:
|
112
|
+
"""Override the file dependencies of the task.
|
113
|
+
|
114
|
+
Args:
|
115
|
+
dependencies (List[str | Path]): The file dependencies to override the task's dependencies.
|
116
|
+
|
117
|
+
Returns:
|
118
|
+
Self: The current instance of the task.
|
119
|
+
"""
|
120
|
+
return self.clear_dependencies().add_dependency(dependencies)
|
121
|
+
|
102
122
|
@property
|
103
123
|
def dependencies_prompt(self) -> str:
|
104
124
|
"""Generate a prompt for the task based on the file dependencies.
|
@@ -109,7 +129,8 @@ class WithDependency(Base):
|
|
109
129
|
return template_manager.render_template(
|
110
130
|
configs.templates.dependencies_template,
|
111
131
|
{
|
112
|
-
(pth := Path(p)).
|
132
|
+
(pth := Path(p)).name: {
|
133
|
+
"path": pth.as_posix(),
|
113
134
|
"exists": pth.exists(),
|
114
135
|
"description": (identity := magika.identify_path(pth)).output.description,
|
115
136
|
"size": f"{pth.stat().st_size / (1024 * 1024) if pth.exists() and pth.is_file() else 0:.3f} MB",
|
fabricatio/models/role.py
CHANGED
@@ -9,7 +9,6 @@ from fabricatio.models.advanced import ProposeTask
|
|
9
9
|
from fabricatio.models.events import Event
|
10
10
|
from fabricatio.models.tool import ToolBox
|
11
11
|
from fabricatio.models.usages import ToolBoxUsage
|
12
|
-
from fabricatio.toolboxes import basic_toolboxes
|
13
12
|
from pydantic import Field
|
14
13
|
|
15
14
|
|
@@ -19,7 +18,7 @@ class Role(ProposeTask, ToolBoxUsage):
|
|
19
18
|
registry: dict[Event | str, WorkFlow] = Field(...)
|
20
19
|
""" The registry of events and workflows."""
|
21
20
|
|
22
|
-
toolboxes: Set[ToolBox] = Field(
|
21
|
+
toolboxes: Set[ToolBox] = Field(default_factory=set)
|
23
22
|
|
24
23
|
def model_post_init(self, __context: Any) -> None:
|
25
24
|
"""Register the workflows in the role to the event bus."""
|
fabricatio/models/task.py
CHANGED
@@ -7,6 +7,8 @@ from asyncio import Queue
|
|
7
7
|
from enum import Enum
|
8
8
|
from typing import Any, List, Optional, Self
|
9
9
|
|
10
|
+
from fabricatio._rust_instances import template_manager
|
11
|
+
from fabricatio.config import configs
|
10
12
|
from fabricatio.core import env
|
11
13
|
from fabricatio.journal import logger
|
12
14
|
from fabricatio.models.events import Event, EventLike
|
@@ -49,8 +51,8 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
|
49
51
|
description: str = Field(default="")
|
50
52
|
"""The description of the task."""
|
51
53
|
|
52
|
-
goal: str = Field(default=
|
53
|
-
"""The goal of the task."""
|
54
|
+
goal: List[str] = Field(default=[])
|
55
|
+
"""The goal of the task, a list of strings."""
|
54
56
|
|
55
57
|
namespace: List[str] = Field(default_factory=list)
|
56
58
|
"""The namespace of the task, a list of namespace segment, as string."""
|
@@ -97,12 +99,12 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
|
97
99
|
return self
|
98
100
|
|
99
101
|
@classmethod
|
100
|
-
def simple_task(cls, name: str, goal: str, description: str) -> Self:
|
102
|
+
def simple_task(cls, name: str, goal: List[str], description: str) -> Self:
|
101
103
|
"""Create a simple task with a name, goal, and description.
|
102
104
|
|
103
105
|
Args:
|
104
106
|
name (str): The name of the task.
|
105
|
-
goal (str): The goal of the task.
|
107
|
+
goal (List[str]): The goal of the task.
|
106
108
|
description (str): The description of the task.
|
107
109
|
|
108
110
|
Returns:
|
@@ -110,18 +112,18 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
|
110
112
|
"""
|
111
113
|
return cls(name=name, goal=goal, description=description)
|
112
114
|
|
113
|
-
def update_task(self, goal: Optional[str] = None, description: Optional[str] = None) -> Self:
|
115
|
+
def update_task(self, goal: Optional[List[str] | str] = None, description: Optional[str] = None) -> Self:
|
114
116
|
"""Update the goal and description of the task.
|
115
117
|
|
116
118
|
Args:
|
117
|
-
goal (str, optional): The new goal of the task.
|
119
|
+
goal (str|List[str], optional): The new goal of the task.
|
118
120
|
description (str, optional): The new description of the task.
|
119
121
|
|
120
122
|
Returns:
|
121
123
|
Task: The updated instance of the `Task` class.
|
122
124
|
"""
|
123
125
|
if goal:
|
124
|
-
self.goal = goal
|
126
|
+
self.goal = goal if isinstance(goal, list) else [goal]
|
125
127
|
if description:
|
126
128
|
self.description = description
|
127
129
|
return self
|
@@ -214,7 +216,7 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
|
214
216
|
Returns:
|
215
217
|
Task: The running instance of the `Task` class.
|
216
218
|
"""
|
217
|
-
logger.info(f"Starting task {self.name}")
|
219
|
+
logger.info(f"Starting task `{self.name}`")
|
218
220
|
self._status = TaskStatus.Running
|
219
221
|
await env.emit_async(self.running_label, self)
|
220
222
|
return self
|
@@ -225,6 +227,7 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
|
225
227
|
Returns:
|
226
228
|
Task: The cancelled instance of the `Task` class.
|
227
229
|
"""
|
230
|
+
logger.info(f"Cancelling task `{self.name}`")
|
228
231
|
self._status = TaskStatus.Cancelled
|
229
232
|
await env.emit_async(self.cancelled_label, self)
|
230
233
|
return self
|
@@ -235,7 +238,7 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
|
235
238
|
Returns:
|
236
239
|
Task: The failed instance of the `Task` class.
|
237
240
|
"""
|
238
|
-
logger.
|
241
|
+
logger.info(f"Failing task `{self.name}`")
|
239
242
|
self._status = TaskStatus.Failed
|
240
243
|
await env.emit_async(self.failed_label, self)
|
241
244
|
return self
|
@@ -267,4 +270,7 @@ class Task[T](WithBriefing, WithJsonExample, WithDependency):
|
|
267
270
|
Returns:
|
268
271
|
str: The briefing of the task.
|
269
272
|
"""
|
270
|
-
return
|
273
|
+
return template_manager.render_template(
|
274
|
+
configs.templates.task_briefing_template,
|
275
|
+
self.model_dump(),
|
276
|
+
)
|