fabricatio 0.1.3__py3-none-any.whl → 0.2.0.dev0__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.
fabricatio/config.py CHANGED
@@ -1,7 +1,17 @@
1
- from typing import List, Literal
1
+ from typing import List, Literal, Optional
2
2
 
3
3
  from appdirs import user_config_dir
4
- from pydantic import BaseModel, ConfigDict, Field, FilePath, HttpUrl, NonNegativeFloat, PositiveInt, SecretStr
4
+ from pydantic import (
5
+ BaseModel,
6
+ ConfigDict,
7
+ DirectoryPath,
8
+ Field,
9
+ FilePath,
10
+ HttpUrl,
11
+ NonNegativeFloat,
12
+ PositiveInt,
13
+ SecretStr,
14
+ )
5
15
  from pydantic_settings import (
6
16
  BaseSettings,
7
17
  DotEnvSettingsSource,
@@ -12,6 +22,8 @@ from pydantic_settings import (
12
22
  TomlConfigSettingsSource,
13
23
  )
14
24
 
25
+ ROAMING_DIR = user_config_dir("fabricatio", "", roaming=True)
26
+
15
27
 
16
28
  class LLMConfig(BaseModel):
17
29
  """LLM configuration class.
@@ -32,59 +44,37 @@ class LLMConfig(BaseModel):
32
44
 
33
45
  model_config = ConfigDict(use_attribute_docstrings=True)
34
46
  api_endpoint: HttpUrl = Field(default=HttpUrl("https://api.openai.com"))
35
- """
36
- OpenAI API Endpoint.
37
- """
47
+ """OpenAI API Endpoint."""
38
48
 
39
49
  api_key: SecretStr = Field(default=SecretStr(""))
40
- """
41
- OpenAI API key. Empty by default for security reasons, should be set before use.
42
- """
50
+ """OpenAI API key. Empty by default for security reasons, should be set before use."""
43
51
 
44
52
  timeout: PositiveInt = Field(default=300)
45
- """
46
- The timeout of the LLM model in seconds. Default is 300 seconds as per request.
47
- """
53
+ """The timeout of the LLM model in seconds. Default is 300 seconds as per request."""
48
54
 
49
55
  max_retries: PositiveInt = Field(default=3)
50
- """
51
- The maximum number of retries. Default is 3 retries.
52
- """
56
+ """The maximum number of retries. Default is 3 retries."""
53
57
 
54
58
  model: str = Field(default="gpt-3.5-turbo")
55
- """
56
- The LLM model name. Set to 'gpt-3.5-turbo' as per request.
57
- """
59
+ """The LLM model name. Set to 'gpt-3.5-turbo' as per request."""
58
60
 
59
61
  temperature: NonNegativeFloat = Field(default=1.0)
60
- """
61
- The temperature of the LLM model. Controls randomness in generation. Set to 1.0 as per request.
62
- """
62
+ """The temperature of the LLM model. Controls randomness in generation. Set to 1.0 as per request."""
63
63
 
64
64
  stop_sign: str | List[str] = Field(default=("\n\n", "User:"))
65
- """
66
- The stop sign of the LLM model. No default stop sign specified.
67
- """
65
+ """The stop sign of the LLM model. No default stop sign specified."""
68
66
 
69
67
  top_p: NonNegativeFloat = Field(default=0.35)
70
- """
71
- The top p of the LLM model. Controls diversity via nucleus sampling. Set to 0.35 as per request.
72
- """
68
+ """The top p of the LLM model. Controls diversity via nucleus sampling. Set to 0.35 as per request."""
73
69
 
74
70
  generation_count: PositiveInt = Field(default=1)
75
- """
76
- The number of generations to generate. Default is 1.
77
- """
71
+ """The number of generations to generate. Default is 1."""
78
72
 
79
73
  stream: bool = Field(default=False)
80
- """
81
- Whether to stream the LLM model's response. Default is False.
82
- """
74
+ """Whether to stream the LLM model's response. Default is False."""
83
75
 
84
76
  max_tokens: PositiveInt = Field(default=8192)
85
- """
86
- The maximum number of tokens to generate. Set to 8192 as per request.
87
- """
77
+ """The maximum number of tokens to generate. Set to 8192 as per request."""
88
78
 
89
79
 
90
80
  class PymitterConfig(BaseModel):
@@ -98,19 +88,13 @@ class PymitterConfig(BaseModel):
98
88
 
99
89
  model_config = ConfigDict(use_attribute_docstrings=True)
100
90
  delimiter: str = Field(default=".", frozen=True)
101
- """
102
- The delimiter used to separate the event name into segments.
103
- """
91
+ """The delimiter used to separate the event name into segments."""
104
92
 
105
93
  new_listener_event: bool = Field(default=False, frozen=True)
106
- """
107
- If set, a newListener event is emitted when a new listener is added.
108
- """
94
+ """If set, a newListener event is emitted when a new listener is added."""
109
95
 
110
96
  max_listeners: int = Field(default=-1, frozen=True)
111
- """
112
- The maximum number of listeners per event.
113
- """
97
+ """The maximum number of listeners per event."""
114
98
 
115
99
 
116
100
  class DebugConfig(BaseModel):
@@ -124,14 +108,28 @@ class DebugConfig(BaseModel):
124
108
  model_config = ConfigDict(use_attribute_docstrings=True)
125
109
 
126
110
  log_level: Literal["DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"] = Field(default="INFO")
127
- """
128
- The log level of the application.
129
- """
111
+ """The log level of the application."""
130
112
 
131
- log_file: FilePath = Field(default=f"{user_config_dir('fabricatio', roaming=True)}.log")
132
- """
133
- The log file of the application.
134
- """
113
+ log_file: FilePath = Field(default=rf"{ROAMING_DIR}\fabricatio.log")
114
+ """The log file of the application."""
115
+
116
+
117
+ class Code2PromptConfig(BaseModel):
118
+ """Code2Prompt configuration class."""
119
+
120
+ model_config = ConfigDict(use_attribute_docstrings=True)
121
+ template_dir: List[DirectoryPath] = Field(
122
+ default_factory=lambda: [r".\c2p_templates", rf"{ROAMING_DIR}\c2p_templates"]
123
+ )
124
+ """The directory containing the templates for code2prompt."""
125
+
126
+
127
+ class MagikaConfig(BaseModel):
128
+ """Magika configuration class."""
129
+
130
+ model_config = ConfigDict(use_attribute_docstrings=True)
131
+ model_dir: Optional[DirectoryPath] = Field(default=None)
132
+ """The directory containing the models for magika."""
135
133
 
136
134
 
137
135
  class Settings(BaseSettings):
@@ -141,6 +139,8 @@ class Settings(BaseSettings):
141
139
  llm (LLMConfig): LLM Configuration
142
140
  debug (DebugConfig): Debug Configuration
143
141
  pymitter (PymitterConfig): Pymitter Configuration
142
+ code2prompt (Code2PromptConfig): Code2Prompt Configuration
143
+ magika (MagikaConfig): Magika Configuration
144
144
  """
145
145
 
146
146
  model_config = SettingsConfigDict(
@@ -148,25 +148,25 @@ class Settings(BaseSettings):
148
148
  env_nested_delimiter="__",
149
149
  pyproject_toml_depth=1,
150
150
  pyproject_toml_table_header=("tool", "fabricatio"),
151
- toml_file=["fabricatio.toml", f"{user_config_dir('fabricatio', roaming=True)}.toml"],
151
+ toml_file=["fabricatio.toml", rf"{ROAMING_DIR}\fabricatio.toml"],
152
152
  env_file=[".env", ".envrc"],
153
153
  use_attribute_docstrings=True,
154
154
  )
155
155
 
156
156
  llm: LLMConfig = Field(default_factory=LLMConfig)
157
- """
158
- LLM Configuration
159
- """
157
+ """LLM Configuration"""
160
158
 
161
159
  debug: DebugConfig = Field(default_factory=DebugConfig)
162
- """
163
- Debug Configuration
164
- """
160
+ """Debug Configuration"""
165
161
 
166
162
  pymitter: PymitterConfig = Field(default_factory=PymitterConfig)
167
- """
168
- Pymitter Configuration
169
- """
163
+ """Pymitter Configuration"""
164
+
165
+ code2prompt: Code2PromptConfig = Field(default_factory=Code2PromptConfig)
166
+ """Code2Prompt Configuration"""
167
+
168
+ magika: MagikaConfig = Field(default_factory=MagikaConfig)
169
+ """Magika Configuration"""
170
170
 
171
171
  @classmethod
172
172
  def settings_customise_sources(
@@ -0,0 +1,56 @@
1
+ from functools import wraps
2
+ from shutil import which
3
+ from typing import Callable
4
+
5
+ from fabricatio.journal import logger
6
+
7
+
8
+ def depend_on_external_cmd[**P, R](bin_name: str, install_tip: str) -> Callable[[Callable[P, R]], Callable[P, R]]:
9
+ """Decorator to check for the presence of an external command.
10
+
11
+ Args:
12
+ bin_name (str): The name of the required binary.
13
+ install_tip (str): Installation instructions for the required binary.
14
+
15
+ Returns:
16
+ Callable[[Callable[P, R]], Callable[P, R]]: A decorator that wraps the function to check for the binary.
17
+
18
+ Raises:
19
+ RuntimeError: If the required binary is not found.
20
+ """
21
+
22
+ def decorator(func: Callable[P, R]) -> Callable[P, R]:
23
+ """Decorator to wrap the function with binary presence check.
24
+
25
+ Args:
26
+ func (Callable[P, R]): The function to be decorated.
27
+
28
+ Returns:
29
+ Callable[P, R]: The wrapped function.
30
+ """
31
+
32
+ @wraps(func)
33
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
34
+ """Wrapper function to check for the presence of the required binary.
35
+
36
+ Args:
37
+ *args: Positional arguments for the function.
38
+ **kwargs: Keyword arguments for the function.
39
+
40
+ Returns:
41
+ R: The result of the function call.
42
+
43
+ Raises:
44
+ RuntimeError: If the required binary is not found.
45
+ """
46
+ if which(bin_name) is None:
47
+ err = (
48
+ f"{bin_name} is required to run function: {func.__name__}, please install it first.\n{install_tip}"
49
+ )
50
+ logger.critical(err)
51
+ raise RuntimeError(err)
52
+ return func(*args, **kwargs)
53
+
54
+ return wrapper
55
+
56
+ return decorator
File without changes
@@ -0,0 +1,5 @@
1
+ from magika import Magika
2
+
3
+ from fabricatio.config import configs
4
+
5
+ magika = Magika(model_dir=configs.magika.model_dir)
@@ -4,6 +4,8 @@ from pydantic import BaseModel, ConfigDict, Field
4
4
 
5
5
  from fabricatio.config import configs
6
6
 
7
+ type EventLike = str | List[str] | Self
8
+
7
9
 
8
10
  class Event(BaseModel):
9
11
  """A class representing an event."""
@@ -14,16 +16,25 @@ class Event(BaseModel):
14
16
  """ The segments of the namespaces."""
15
17
 
16
18
  @classmethod
17
- def from_string(cls, event: str) -> Self:
18
- """Create an Event instance from a string.
19
+ def instantiate_from(cls, event: EventLike) -> Self:
20
+ """Create an Event instance from a string or list of strings or an Event instance.
19
21
 
20
22
  Args:
21
- event (str): The event string.
23
+ event (EventLike): The event to instantiate from.
22
24
 
23
25
  Returns:
24
26
  Event: The Event instance.
25
27
  """
26
- return cls(segments=event.split(configs.pymitter.delimiter))
28
+ if isinstance(event, Event):
29
+ return event.clone()
30
+ if isinstance(event, str):
31
+ event = event.split(configs.pymitter.delimiter)
32
+
33
+ return cls(segments=event)
34
+
35
+ def derive(self, event: EventLike) -> Self:
36
+ """Derive a new event from this event and another event or a string."""
37
+ return self.clone().concat(event)
27
38
 
28
39
  def collapse(self) -> str:
29
40
  """Collapse the event into a string."""
@@ -41,6 +52,10 @@ class Event(BaseModel):
41
52
  self.segments.append(segment)
42
53
  return self
43
54
 
55
+ def push_wildcard(self) -> Self:
56
+ """Push a wildcard segment to the event."""
57
+ return self.push("*")
58
+
44
59
  def pop(self) -> str:
45
60
  """Pop a segment from the event."""
46
61
  return self.segments.pop()
@@ -50,19 +65,15 @@ class Event(BaseModel):
50
65
  self.segments.clear()
51
66
  return self
52
67
 
53
- def concat(self, event: Self | str) -> Self:
68
+ def concat(self, event: EventLike) -> Self:
54
69
  """Concatenate another event to this event."""
55
- if isinstance(event, str):
56
- event = Event.from_string(event)
57
- self.segments.extend(event.segments)
70
+ self.segments.extend(Event.instantiate_from(event).segments)
58
71
  return self
59
72
 
60
73
  def __hash__(self) -> int:
61
74
  """Return the hash of the event, using the collapsed string."""
62
75
  return hash(self.collapse())
63
76
 
64
- def __eq__(self, other: Self | str) -> bool:
77
+ def __eq__(self, other: str | List[str] | Self) -> bool:
65
78
  """Check if the event is equal to another event or a string."""
66
- if isinstance(other, Event):
67
- other = other.collapse()
68
- return self.collapse() == other
79
+ return self.collapse() == Event.instantiate_from(other).collapse()
@@ -1,4 +1,5 @@
1
1
  from asyncio import Queue
2
+ from pathlib import Path
2
3
  from typing import Callable, Dict, Iterable, List, Optional, Self
3
4
 
4
5
  import litellm
@@ -17,6 +18,7 @@ from pydantic import (
17
18
  )
18
19
 
19
20
  from fabricatio.config import configs
21
+ from fabricatio.fs.readers import magika
20
22
  from fabricatio.models.utils import Messages
21
23
 
22
24
 
@@ -464,3 +466,52 @@ class WithJsonExample(Base):
464
466
  {field_name: field_info.description for field_name, field_info in cls.model_fields.items()},
465
467
  option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS,
466
468
  ).decode()
469
+
470
+
471
+ class WithDependency(Base):
472
+ """Class that manages file dependencies."""
473
+
474
+ dependencies: List[str] = Field(default_factory=list)
475
+ """The file dependencies of the task, a list of file paths."""
476
+
477
+ def add_dependency[P: str | Path](self, dependency: P | List[P]) -> Self:
478
+ """Add a file dependency to the task.
479
+
480
+ Args:
481
+ dependency (str | Path | List[str | Path]): The file dependency to add to the task.
482
+
483
+ Returns:
484
+ Self: The current instance of the task.
485
+ """
486
+ if not isinstance(dependency, list):
487
+ dependency = [dependency]
488
+ self.dependencies.extend(Path(d).as_posix() for d in dependency)
489
+ return self
490
+
491
+ def remove_dependency[P: str | Path](self, dependency: P | List[P]) -> Self:
492
+ """Remove a file dependency from the task.
493
+
494
+ Args:
495
+ dependency (str | Path | List[str | Path]): The file dependency to remove from the task.
496
+
497
+ Returns:
498
+ Self: The current instance of the task.
499
+ """
500
+ if not isinstance(dependency, list):
501
+ dependency = [dependency]
502
+ for d in dependency:
503
+ self.dependencies.remove(Path(d).as_posix())
504
+ return self
505
+
506
+ def generate_prompt(self) -> str:
507
+ """Generate a prompt for the task based on the file dependencies.
508
+
509
+ Returns:
510
+ str: The generated prompt for the task.
511
+ """
512
+ contents = [Path(d).read_text("utf-8") for d in self.dependencies]
513
+ recognized = [magika.identify_path(c) for c in contents]
514
+ out = ""
515
+ for r, p, c in zip(recognized, self.dependencies, contents, strict=False):
516
+ out += f"---\n\n> {p}\n```{r.dl.ct_label}\n{c}\n```\n\n"
517
+ return out
fabricatio/models/task.py CHANGED
@@ -5,15 +5,14 @@ It includes methods to manage the task's lifecycle, such as starting, finishing,
5
5
 
6
6
  from asyncio import Queue
7
7
  from enum import Enum
8
- from typing import Optional, Self
8
+ from typing import Any, List, Optional, Self
9
9
 
10
10
  from pydantic import Field, PrivateAttr
11
11
 
12
- from fabricatio.config import configs
13
12
  from fabricatio.core import env
14
13
  from fabricatio.journal import logger
15
14
  from fabricatio.models.events import Event
16
- from fabricatio.models.generic import WithBriefing, WithJsonExample
15
+ from fabricatio.models.generic import WithBriefing, WithDependency, WithJsonExample
17
16
 
18
17
 
19
18
  class TaskStatus(Enum):
@@ -34,13 +33,15 @@ class TaskStatus(Enum):
34
33
  Cancelled = "cancelled"
35
34
 
36
35
 
37
- class Task[T](WithBriefing, WithJsonExample):
36
+ class Task[T](WithBriefing, WithJsonExample, WithDependency):
38
37
  """A class representing a task with a status and output.
39
38
 
40
39
  Attributes:
41
40
  name (str): The name of the task.
42
41
  description (str): The description of the task.
43
42
  goal (str): The goal of the task.
43
+ dependencies (List[str]): The file dependencies of the task, a list of file paths.
44
+ namespace (List[str]): The namespace of the task, a list of namespace segment, as string.
44
45
  """
45
46
 
46
47
  name: str = Field(...)
@@ -52,12 +53,35 @@ class Task[T](WithBriefing, WithJsonExample):
52
53
  goal: str = Field(default="")
53
54
  """The goal of the task."""
54
55
 
56
+ namespace: List[str] = Field(default_factory=list)
57
+ """The namespace of the task, a list of namespace segment, as string."""
58
+
55
59
  _output: Queue = PrivateAttr(default_factory=lambda: Queue(maxsize=1))
56
60
  """The output queue of the task."""
57
61
 
58
62
  _status: TaskStatus = PrivateAttr(default=TaskStatus.Pending)
59
63
  """The status of the task."""
60
64
 
65
+ _namespace: Event = PrivateAttr(default_factory=Event)
66
+ """The namespace of the task as an event, which is generated from the namespace list."""
67
+
68
+ def model_post_init(self, __context: Any) -> None:
69
+ """Initialize the task with a namespace event."""
70
+ self._namespace.segments.extend(self.namespace)
71
+
72
+ def move_to(self, new_namespace: List[str]) -> Self:
73
+ """Move the task to a new namespace.
74
+
75
+ Args:
76
+ new_namespace (List[str]): The new namespace to move the task to.
77
+
78
+ Returns:
79
+ Task: The moved instance of the `Task` class.
80
+ """
81
+ self.namespace = new_namespace
82
+ self._namespace.clear().concat(new_namespace)
83
+ return self
84
+
61
85
  @classmethod
62
86
  def simple_task(cls, name: str, goal: str, description: str) -> Self:
63
87
  """Create a simple task with a name, goal, and description.
@@ -106,7 +130,7 @@ class Task[T](WithBriefing, WithJsonExample):
106
130
  Returns:
107
131
  str: The formatted status label.
108
132
  """
109
- return f"{self.name}{configs.pymitter.delimiter}{status.value}"
133
+ return self._namespace.derive(self.name).push(status.value).collapse()
110
134
 
111
135
  @property
112
136
  def pending_label(self) -> str:
@@ -202,36 +226,24 @@ class Task[T](WithBriefing, WithJsonExample):
202
226
  await env.emit_async(self.failed_label, self)
203
227
  return self
204
228
 
205
- async def publish(self, event_namespace: Event | str = "") -> Self:
206
- """Publish the task with an optional event namespace.
207
-
208
- Args:
209
- event_namespace (Event | str, optional): The event namespace to use. Defaults to an empty string.
229
+ async def publish(self) -> Self:
230
+ """Publish the task to the event bus.
210
231
 
211
232
  Returns:
212
- Task: The published instance of the `Task` class.
233
+ Task: The published instance of the `Task` class
213
234
  """
214
- if isinstance(event_namespace, str):
215
- event_namespace = Event.from_string(event_namespace)
216
-
217
235
  logger.info(f"Publishing task {self.name}")
218
- await env.emit_async(event_namespace.concat(self.pending_label).collapse(), self)
236
+ await env.emit_async(self.pending_label, self)
219
237
  return self
220
238
 
221
- async def delegate(self, event_namespace: Event | str = "") -> T:
222
- """Delegate the task with an optional event namespace and return the output.
223
-
224
- Args:
225
- event_namespace (Event | str, optional): The event namespace to use. Defaults to an empty string.
239
+ async def delegate(self) -> T:
240
+ """Delegate the task to the event bus and wait for the output.
226
241
 
227
242
  Returns:
228
- T: The output of the task.
243
+ T: The output of the task
229
244
  """
230
- if isinstance(event_namespace, str):
231
- event_namespace = Event.from_string(event_namespace)
232
-
233
245
  logger.info(f"Delegating task {self.name}")
234
- await env.emit_async(event_namespace.concat(self.pending_label).collapse(), self)
246
+ await env.emit_async(self.pending_label, self)
235
247
  return await self.get_output()
236
248
 
237
249
  @property
fabricatio/parser.py CHANGED
@@ -64,3 +64,4 @@ class Capture(Base):
64
64
 
65
65
  JsonCapture = Capture.capture_code_block("json")
66
66
  PythonCapture = Capture.capture_code_block("python")
67
+ CodeBlockCapture = Capture.capture_code_block("")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fabricatio
3
- Version: 0.1.3
3
+ Version: 0.2.0.dev0
4
4
  Summary: A LLM multi-agent framework.
5
5
  Author-email: Whth <zettainspector@foxmail.com>
6
6
  License: MIT License
@@ -37,16 +37,18 @@ Requires-Dist: aiohttp>=3.11.11
37
37
  Requires-Dist: aiomultiprocess>=0.9.1
38
38
  Requires-Dist: appdirs>=1.4.4
39
39
  Requires-Dist: asyncio>=3.4.3
40
+ Requires-Dist: code2prompt
40
41
  Requires-Dist: gitpython>=3.1.44
41
42
  Requires-Dist: litellm>=1.60.0
42
43
  Requires-Dist: loguru>=0.7.3
44
+ Requires-Dist: magika>=0.5.1
43
45
  Requires-Dist: orjson>=3.10.15
44
46
  Requires-Dist: pydantic-settings>=2.7.1
45
47
  Requires-Dist: pydantic>=2.10.6
46
48
  Requires-Dist: pymitter>=1.0.0
49
+ Requires-Dist: questionary>=2.1.0
47
50
  Requires-Dist: regex>=2024.11.6
48
51
  Requires-Dist: rich>=13.9.4
49
- Requires-Dist: shutilwhich>=1.1.0
50
52
  Description-Content-Type: text/markdown
51
53
 
52
54
  ## Usage
@@ -1,21 +1,24 @@
1
1
  fabricatio/__init__.py,sha256=nFPtohqceECRYzU-WlVT6o4oSaKN0vGok-w9JIaiJfs,644
2
- fabricatio/config.py,sha256=EOlVkuEBAHESAlrGtolGwEG2YrTaJPhEGPKS7QDxrx0,6995
2
+ fabricatio/config.py,sha256=emkIpaXRQykAX_C2ND8tKR2DQUJJEN0mvdMDTklwOXw,7823
3
3
  fabricatio/core.py,sha256=B6KBIfBRF023HF0UUaUprEkQd6sT7G_pexGXQ9btJnE,5788
4
+ fabricatio/decorators.py,sha256=Qsyb-_cDwtXY5yhyLrYZEAlrHh5ZuEooQ8vEOUAxj8k,1855
4
5
  fabricatio/journal.py,sha256=CW9HePtgTiboOyPTExq9GjG5BseZcbc-S6lxDXrpmv0,667
5
- fabricatio/parser.py,sha256=On_YUCvOuA0FA_NtDVNJqKp7KEO_sUE89oO_WnkEhQ4,2314
6
+ fabricatio/parser.py,sha256=6PNFNNyHNkNG7vTS1ejFc4vCzl1OCy4bqB0e4Ty_-Qs,2365
6
7
  fabricatio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
8
  fabricatio/actions/__init__.py,sha256=n3lwq9FPNtvfLu2L1pX4UkwiPITU7luk-b4aMJyjIC8,109
8
9
  fabricatio/actions/transmission.py,sha256=Azog4ItVk7aASdYzTwzyckzYG2hDFSXctnA7qp-Qlq0,502
10
+ fabricatio/fs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ fabricatio/fs/readers.py,sha256=mw0VUH3P7Wk0SMlcQm2yOfjEz5C3mQ_kjduAjecaxgY,123
9
12
  fabricatio/models/action.py,sha256=M-12dc-nQiNJU6Y9j-dr4Ef3642vRvzHlzxekBepzaU,3358
10
- fabricatio/models/events.py,sha256=PlavKOD94Q9Q9iPoQPkf9HJdznBtzuSUrPtUoVtkQxU,2143
11
- fabricatio/models/generic.py,sha256=Sxpx0BO0t85YF5Lwks6F165N6TJsDe7xym28dQG5Mqs,17681
13
+ fabricatio/models/events.py,sha256=pW3sfxEFWTafbP4bn4hVFSe8qloYrrzOgi9oMCqAEgw,2604
14
+ fabricatio/models/generic.py,sha256=noHow8dUjMnNiasl2ZHaZeCMpxzDme9QvxTetoyB45w,19539
12
15
  fabricatio/models/role.py,sha256=jdabuYRXwgvpYoNwvazygDiZHGGQApUIIKltniu78O8,2151
13
- fabricatio/models/task.py,sha256=8IXT192t5EXVHAdHj45DJNdBhdA2xmh36S_vKyEw6y0,7757
16
+ fabricatio/models/task.py,sha256=Qc16UeeTMaFjG2-sXafyOrjOS7H_0RluE9sFNwArDlI,8179
14
17
  fabricatio/models/tool.py,sha256=UkEp1Nzbl5wZX21q_Z2VkpiJmVDSdoGDzINQniO8hSY,3536
15
18
  fabricatio/models/utils.py,sha256=2mgXla9_K3dnRrz6hIKzmltTYPmvDk0MBjjEBkCXTdg,2474
16
19
  fabricatio/toolboxes/__init__.py,sha256=bjefmPd7wBaWhbZzdMPXvrjMTeRzlUh_Dev2PUAc124,158
17
20
  fabricatio/toolboxes/task.py,sha256=xgyPetm2R_HlQwpzE8YPnBN7QOYLd0-T8E6QPZG1PPQ,204
18
- fabricatio-0.1.3.dist-info/METADATA,sha256=pDZPikewIva_s6riDaxhlOmvd92ls_JoS_VqETPwDdM,3797
19
- fabricatio-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- fabricatio-0.1.3.dist-info/licenses/LICENSE,sha256=do7J7EiCGbq0QPbMAL_FqLYufXpHnCnXBOuqVPwSV8Y,1088
21
- fabricatio-0.1.3.dist-info/RECORD,,
21
+ fabricatio-0.2.0.dev0.dist-info/METADATA,sha256=keLz2I0t_VqaU0Xx5rgSIW66aZqSeJLKIsi9Vjw89vc,3858
22
+ fabricatio-0.2.0.dev0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ fabricatio-0.2.0.dev0.dist-info/licenses/LICENSE,sha256=do7J7EiCGbq0QPbMAL_FqLYufXpHnCnXBOuqVPwSV8Y,1088
24
+ fabricatio-0.2.0.dev0.dist-info/RECORD,,