versionhq 1.1.9.0__py3-none-any.whl → 1.1.9.2__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.
versionhq/__init__.py CHANGED
@@ -18,7 +18,7 @@ from versionhq.tool.model import Tool
18
18
  from versionhq.tool.composio import Composio
19
19
 
20
20
 
21
- __version__ = "1.1.9.0"
21
+ __version__ = "1.1.9.2"
22
22
  __all__ = [
23
23
  "Agent",
24
24
  "Customer",
@@ -6,8 +6,8 @@ from pydantic import BaseModel, PrivateAttr
6
6
  class CacheHandler(BaseModel):
7
7
  _cache: Dict[str, Any] = PrivateAttr(default_factory=dict)
8
8
 
9
- def add(self, tool, input, output):
9
+ def add(self, tool: str, input: str, output: Any) -> None:
10
10
  self._cache[f"{tool}-{input}"] = output
11
11
 
12
- def read(self, tool, input) -> Optional[str]:
12
+ def read(self, tool: str, input: str) -> Optional[str]:
13
13
  return self._cache.get(f"{tool}-{input}")
@@ -10,23 +10,21 @@ class Printer:
10
10
  self._print_purple(content)
11
11
  elif color == "red":
12
12
  self._print_red(content)
13
- elif color == "bold_green":
14
- self._print_bold_green(content)
15
- elif color == "bold_purple":
16
- self._print_bold_purple(content)
17
- elif color == "bold_blue":
18
- self._print_bold_blue(content)
13
+ elif color == "green":
14
+ self._print_green(content)
15
+ elif color == "purple":
16
+ self._print_purple(content)
17
+ elif color == "blue":
18
+ self._print_blue(content)
19
19
  elif color == "yellow":
20
20
  self._print_yellow(content)
21
- elif color == "bold_yellow":
22
- self._print_bold_yellow(content)
23
21
  else:
24
22
  print(content)
25
23
 
26
- def _print_bold_purple(self, content):
24
+ def _print_purple(self, content):
27
25
  print("\033[1m\033[95m {}\033[00m".format(content))
28
26
 
29
- def _print_bold_green(self, content):
27
+ def _print_green(self, content):
30
28
  print("\033[1m\033[92m {}\033[00m".format(content))
31
29
 
32
30
  def _print_purple(self, content):
@@ -35,23 +33,18 @@ class Printer:
35
33
  def _print_red(self, content):
36
34
  print("\033[91m {}\033[00m".format(content))
37
35
 
38
- def _print_bold_blue(self, content):
36
+ def _print_blue(self, content):
39
37
  print("\033[1m\033[94m {}\033[00m".format(content))
40
38
 
41
39
  def _print_yellow(self, content):
42
- print("\033[93m {}\033[00m".format(content))
43
-
44
- def _print_bold_yellow(self, content):
45
40
  print("\033[1m\033[93m {}\033[00m".format(content))
46
41
 
47
42
 
48
43
  class Logger(BaseModel):
49
- verbose: bool = Field(default=False)
44
+ verbose: bool = Field(default=True)
50
45
  _printer: Printer = PrivateAttr(default_factory=Printer)
51
46
 
52
- def log(self, level, message, color="bold_yellow"):
47
+ def log(self, level, message, color="yellow"):
53
48
  if self.verbose:
54
49
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
55
- self._printer.print(
56
- f"\n[{timestamp}][{level.upper()}]: {message}", color=color
57
- )
50
+ self._printer.print(f"\n[{timestamp}][{level.upper()}]: {message}", color=color)
@@ -1,6 +1,7 @@
1
1
  import threading
2
2
  import time
3
3
  from typing import Optional
4
+ from typing_extensions import Self
4
5
 
5
6
  from pydantic import BaseModel, Field, PrivateAttr, model_validator
6
7
 
@@ -16,14 +17,14 @@ class RPMController(BaseModel):
16
17
  _shutdown_flag: bool = PrivateAttr(default=False)
17
18
 
18
19
  @model_validator(mode="after")
19
- def reset_counter(self):
20
+ def reset_counter(self) -> Self:
20
21
  if self.max_rpm is not None:
21
22
  if not self._shutdown_flag:
22
23
  self._lock = threading.Lock()
23
24
  self._reset_request_count()
24
25
  return self
25
26
 
26
- def check_or_wait(self):
27
+ def check_or_wait(self) -> bool:
27
28
  if self.max_rpm is None:
28
29
  return True
29
30
 
@@ -46,16 +47,16 @@ class RPMController(BaseModel):
46
47
  else:
47
48
  return _check_and_increment()
48
49
 
49
- def stop_rpm_counter(self):
50
+ def stop_rpm_counter(self) -> None:
50
51
  if self._timer:
51
52
  self._timer.cancel()
52
53
  self._timer = None
53
54
 
54
- def _wait_for_next_minute(self):
55
+ def _wait_for_next_minute(self) -> None:
55
56
  time.sleep(60)
56
57
  self._current_rpm = 0
57
58
 
58
- def _reset_request_count(self):
59
+ def _reset_request_count(self) -> None:
59
60
  def _reset():
60
61
  self._current_rpm = 0
61
62
  if not self._shutdown_flag:
@@ -12,7 +12,7 @@ class UsageMetrics(BaseModel):
12
12
  completion_tokens: int = Field(default=0, description="Number of tokens used in completions")
13
13
  successful_requests: int = Field(default=0, description="Number of successful requests made")
14
14
 
15
- def add_usage_metrics(self, usage_metrics: "UsageMetrics"):
15
+ def add_usage_metrics(self, usage_metrics: "UsageMetrics") -> None:
16
16
  """
17
17
  Add the usage metrics from another UsageMetrics object.
18
18
  """
versionhq/agent/model.py CHANGED
@@ -1,22 +1,19 @@
1
1
  import os
2
2
  import uuid
3
- from abc import ABC
4
3
  from typing import Any, Dict, List, Optional, TypeVar
4
+ from typing_extensions import Self
5
5
  from dotenv import load_dotenv
6
6
  from pydantic import UUID4, BaseModel, Field, InstanceOf, PrivateAttr, model_validator, field_validator
7
7
  from pydantic_core import PydanticCustomError
8
8
 
9
- from versionhq._utils.cache_handler import CacheHandler
10
9
  from versionhq._utils.logger import Logger
11
10
  from versionhq._utils.rpm_controller import RPMController
12
11
  from versionhq._utils.usage_metrics import UsageMetrics
13
- from versionhq.agent.parser import AgentAction
14
12
  from versionhq.llm.llm_vars import LLM_VARS
15
13
  from versionhq.llm.model import LLM, DEFAULT_CONTEXT_WINDOW
16
14
  from versionhq.task import TaskOutputFormat
17
15
  from versionhq.task.model import ResponseField
18
16
  from versionhq.tool.model import Tool, ToolSet
19
- from versionhq.tool.tool_handler import ToolHandler
20
17
 
21
18
  load_dotenv(override=True)
22
19
  T = TypeVar("T", bound="Agent")
@@ -51,18 +48,18 @@ class TokenProcess:
51
48
  completion_tokens: int = 0
52
49
  successful_requests: int = 0
53
50
 
54
- def sum_prompt_tokens(self, tokens: int):
51
+ def sum_prompt_tokens(self, tokens: int) -> None:
55
52
  self.prompt_tokens = self.prompt_tokens + tokens
56
53
  self.total_tokens = self.total_tokens + tokens
57
54
 
58
- def sum_completion_tokens(self, tokens: int):
55
+ def sum_completion_tokens(self, tokens: int) -> None:
59
56
  self.completion_tokens = self.completion_tokens + tokens
60
57
  self.total_tokens = self.total_tokens + tokens
61
58
 
62
- def sum_cached_prompt_tokens(self, tokens: int):
59
+ def sum_cached_prompt_tokens(self, tokens: int) -> None:
63
60
  self.cached_prompt_tokens = self.cached_prompt_tokens + tokens
64
61
 
65
- def sum_successful_requests(self, requests: int):
62
+ def sum_successful_requests(self, requests: int) -> None:
66
63
  self.successful_requests = self.successful_requests + requests
67
64
 
68
65
  def get_summary(self) -> UsageMetrics:
@@ -76,7 +73,7 @@ class TokenProcess:
76
73
 
77
74
 
78
75
  # @track_agent()
79
- class Agent(ABC, BaseModel):
76
+ class Agent(BaseModel):
80
77
  """
81
78
  Agent class that run on LLM.
82
79
  Agents execute tasks alone or in the team, using RAG tools and knowledge base if any.
@@ -97,10 +94,7 @@ class Agent(ABC, BaseModel):
97
94
  backstory: Optional[str] = Field(default=None, description="system context passed to the LLM")
98
95
  knowledge: Optional[str] = Field(default=None, description="external knowledge fed to the agent")
99
96
  skillsets: Optional[List[str]] = Field(default_factory=list)
100
-
101
- # tools
102
- tools: Optional[List[Any]] = Field(default_factory=list)
103
- tool_handler: InstanceOf[ToolHandler] = Field(default=None, description="handle tool cache and last used tool")
97
+ tools: Optional[List[Tool | Any]] = Field(default_factory=list)
104
98
 
105
99
  # team, task execution rules
106
100
  team: Optional[List[Any]] = Field(default=None, description="Team to which the agent belongs")
@@ -126,10 +120,7 @@ class Agent(ABC, BaseModel):
126
120
 
127
121
  # config, cache, error handling
128
122
  config: Optional[Dict[str, Any]] = Field(default=None, exclude=True, description="Configuration for the agent")
129
- cache: bool = Field(default=True, description="Whether the agent should use a cache for tool usage.")
130
- cache_handler: InstanceOf[CacheHandler] = Field(default=None, description="An instance of the CacheHandler class.")
131
123
  formatting_errors: int = Field(default=0, description="Number of formatting errors.")
132
- verbose: bool = Field(default=True, description="Verbose mode for the Agent Execution")
133
124
  agent_ops_agent_name: str = None
134
125
  agent_ops_agent_id: str = None
135
126
 
@@ -146,7 +137,7 @@ class Agent(ABC, BaseModel):
146
137
 
147
138
 
148
139
  @model_validator(mode="after")
149
- def validate_required_fields(self):
140
+ def validate_required_fields(self) -> Self:
150
141
  required_fields = ["role", "goal"]
151
142
  for field in required_fields:
152
143
  if getattr(self, field) is None:
@@ -155,7 +146,7 @@ class Agent(ABC, BaseModel):
155
146
 
156
147
 
157
148
  @model_validator(mode="after")
158
- def set_up_llm(self):
149
+ def set_up_llm(self) -> Self:
159
150
  """
160
151
  Set up the base model and function calling model (if any) using the LLM class.
161
152
  Pass the model config params: `llm`, `max_tokens`, `max_execution_time`, `step_callback`,`respect_context_window` to the LLM class.
@@ -270,31 +261,42 @@ class Agent(ABC, BaseModel):
270
261
 
271
262
 
272
263
  @model_validator(mode="after")
273
- def set_up_tools(self):
264
+ def set_up_tools(self) -> Self:
274
265
  """
275
266
  Similar to the LLM set up, when the agent has tools, we will declare them using the Tool class.
276
267
  """
277
-
278
268
  if not self.tools:
279
269
  pass
280
270
 
281
271
  else:
282
- tools_in_class_format = []
283
- for tool in self.tools:
284
- if isinstance(tool, Tool):
285
- tools_in_class_format.append(tool)
286
- elif isinstance(tool, str):
287
- tool_to_add = Tool(name=tool)
288
- tools_in_class_format.append(tool_to_add)
272
+ tool_list = []
273
+ def empty_func():
274
+ return "empty function"
275
+
276
+ for item in self.tools:
277
+ if isinstance(item, Tool):
278
+ tool_list.append(item)
279
+
280
+ elif isinstance(item, dict):
281
+ if "function" not in item:
282
+ setattr(item, "function", empty_func)
283
+ tool = Tool(**item)
284
+ tool_list.append(tool)
285
+
286
+ elif isinstance(item, str):
287
+ tool = Tool(name=item, function=empty_func)
288
+ tool_list.append(tool)
289
+
289
290
  else:
290
- pass
291
- self.tools = tools_in_class_format
291
+ tool_list.append(item) # address custom tool
292
+
293
+ self.tools = tool_list
292
294
 
293
295
  return self
294
296
 
295
297
 
296
298
  @model_validator(mode="after")
297
- def set_up_backstory(self):
299
+ def set_up_backstory(self) -> Self:
298
300
  """
299
301
  Set up the backstory using a templated BACKSTORY when the backstory is None
300
302
  """
@@ -305,7 +307,7 @@ class Agent(ABC, BaseModel):
305
307
  role=self.role,
306
308
  knowledge=self.knowledge if isinstance(self.knowledge, str) else None,
307
309
  skillsets=", ".join([item for item in self.skillsets]),
308
- rag_tool_overview=", ".join([item.name for item in self.tools]),
310
+ rag_tool_overview=", ".join([item.name for item in self.tools if hasattr(item, "name")]) if self.tools else "",
309
311
  goal=self.goal,
310
312
  )
311
313
  self.backstory = backstory
@@ -313,9 +315,7 @@ class Agent(ABC, BaseModel):
313
315
  return self
314
316
 
315
317
 
316
- def invoke(
317
- self, prompts: str, output_formats: List[TaskOutputFormat], response_fields: List[ResponseField], **kwargs
318
- ) -> Dict[str, Any]:
318
+ def invoke(self, prompts: str, output_formats: List[TaskOutputFormat], response_fields: List[ResponseField], **kwargs) -> Dict[str, Any]:
319
319
  """
320
320
  Receive the system prompt in string and create formatted prompts using the system prompt and the agent's backstory.
321
321
  Then call the base model.
@@ -358,11 +358,10 @@ class Agent(ABC, BaseModel):
358
358
  return {"output": response.output if hasattr(response, "output") else response}
359
359
 
360
360
 
361
- def execute_task(self, task, context: Optional[str] = None, tools: Optional[str] = None) -> str:
361
+ def execute_task(self, task, context: Optional[str] = None) -> str:
362
362
  """
363
- Execute the task and return the output in string.
364
- To simplify, the tools are cascaded from the `tools_called` under the `task` Task instance if any.
365
- When the tools are given, the agent must use them.
363
+ Execute the task and return the response in string.
364
+ The agent utilizes the tools in task or their own tools if the task.can_use_agent_tools is True.
366
365
  The agent must consider the context to excute the task as well when it is given.
367
366
  """
368
367
 
@@ -371,13 +370,29 @@ class Agent(ABC, BaseModel):
371
370
  task_prompt += context
372
371
 
373
372
  tool_results = []
374
- if task.tools_called:
375
- for tool_called in task.tools_called:
376
- tool_result = tool_called.tool.run()
373
+ if task.tools:
374
+ for item in task.tools:
375
+ if isinstance(item, ToolSet):
376
+ tool_result = item.tool.run(**item.kwargs)
377
+ tool_results.append(tool_result)
378
+ elif isinstance(item, Tool):
379
+ tool_result = item.run()
380
+ tool_results.append(tool_result)
381
+ else:
382
+ try:
383
+ item.run()
384
+ except:
385
+ pass
386
+
387
+ if task.can_use_agent_tools is True and self.tools:
388
+ for tool in self.tools:
389
+ tool_result = tool.run()
377
390
  tool_results.append(tool_result)
378
391
 
379
- if task.take_tool_res_as_final:
380
- return tool_results
392
+ if task.take_tool_res_as_final:
393
+ return tool_results
394
+
395
+
381
396
 
382
397
  # if self.team and self.team._train:
383
398
  # task_prompt = self._training_handler(task_prompt=task_prompt)
@@ -395,9 +410,7 @@ class Agent(ABC, BaseModel):
395
410
  self._times_executed += 1
396
411
  if self._times_executed > self.max_retry_limit:
397
412
  raise e
398
- result = self.execute_task(
399
- task, context, [tool_called.tool for tool_called in task.tools_called]
400
- )
413
+ result = self.execute_task(task, context)
401
414
 
402
415
  if self.max_rpm and self._rpm_controller:
403
416
  self._rpm_controller.stop_rpm_counter()
versionhq/agent/parser.py CHANGED
@@ -73,9 +73,7 @@ class AgentParser:
73
73
  def parse(self, text: str) -> AgentAction | AgentFinish:
74
74
  thought = self._extract_thought(text)
75
75
  includes_answer = FINAL_ANSWER_ACTION in text
76
- regex = (
77
- r"Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
78
- )
76
+ regex = r"Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"
79
77
  action_match = re.search(regex, text, re.DOTALL)
80
78
  if action_match:
81
79
  if includes_answer:
@@ -127,18 +125,9 @@ class AgentParser:
127
125
  def _safe_repair_json(self, tool_input: str) -> str:
128
126
  UNABLE_TO_REPAIR_JSON_RESULTS = ['""', "{}"]
129
127
 
130
- # Skip repair if the input starts and ends with square brackets
131
- # Explanation: The JSON parser has issues handling inputs that are enclosed in square brackets ('[]').
132
- # These are typically valid JSON arrays or strings that do not require repair. Attempting to repair such inputs
133
- # might lead to unintended alterations, such as wrapping the entire input in additional layers or modifying
134
- # the structure in a way that changes its meaning. By skipping the repair for inputs that start and end with
135
- # square brackets, we preserve the integrity of these valid JSON structures and avoid unnecessary modifications.
136
128
  if tool_input.startswith("[") and tool_input.endswith("]"):
137
129
  return tool_input
138
130
 
139
- # Before repair, handle common LLM issues:
140
- # 1. Replace """ with " to avoid JSON parser errors
141
-
142
131
  tool_input = tool_input.replace('"""', '"')
143
132
 
144
133
  result = repair_json(tool_input)
@@ -0,0 +1,5 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Status(str, Enum):
5
+ ON_WORKFLOW = "on_workflow"
@@ -1,57 +1,53 @@
1
1
  import uuid
2
- from abc import ABC
2
+ from abc import ABC, abstractmethod
3
3
  from typing import Any, Dict, List, Callable, Type, Optional, get_args, get_origin
4
- from pydantic import (
5
- UUID4,
6
- InstanceOf,
7
- BaseModel,
8
- ConfigDict,
9
- Field,
10
- create_model,
11
- field_validator,
12
- model_validator,
13
- )
4
+ from pydantic import UUID4, InstanceOf, BaseModel, ConfigDict, Field, create_model, field_validator, model_validator
14
5
  from pydantic_core import PydanticCustomError
15
6
 
16
7
  from versionhq.clients.product.model import Product, ProductProvider
8
+ from versionhq.clients.customer import Status
17
9
 
18
10
 
19
- class Customer(ABC, BaseModel):
11
+ class BaseCustomer(ABC, BaseModel):
20
12
  """
21
- Store the minimal information on the customer.
13
+ Abstract base class for the base customer
22
14
  """
23
15
 
24
16
  id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)
25
17
  name: Optional[str] = Field(default=None, description="customer's name if any")
26
- product_list: Optional[List[Product]] = Field(
27
- default=list, description="store products that the customer is associated with"
28
- )
29
- analysis: str = Field(
30
- default=None, description="store the latest analysis results on the customer"
31
- )
32
- on_workflow: bool = Field(
33
- default=False, description="`True` if they are on some messaging workflows"
34
- )
35
- on: Optional[str] = Field(
36
- default=None, description="destination service for this customer if any"
37
- )
18
+ products: Optional[List[Product]] = Field(default=list, description="store products that the customer is associated with")
19
+ analysis: str = Field(default=None, description="store the latest analysis results on the customer")
20
+ status: str = Field(default=Status.ON_WORKFLOW)
21
+
38
22
 
39
23
  @field_validator("id", mode="before")
40
24
  @classmethod
41
25
  def _deny_user_set_id(cls, v: Optional[UUID4]) -> None:
42
26
  if v:
43
- raise PydanticCustomError(
44
- "may_not_set_field", "This field is not to be set by the user.", {}
45
- )
27
+ raise PydanticCustomError("may_not_set_field", "This field is not to be set by the user.", {})
28
+
46
29
 
47
30
  def customer_to(self) -> List[ProductProvider]:
48
31
  """
49
32
  Return list of ProductProvider if the customer has `product_list`
50
33
  """
51
34
 
52
- res = list
53
- if self.product_list:
54
- for item in self.product_list:
35
+ res = []
36
+ if self.products:
37
+ for item in self.products:
55
38
  if item.provider not in res:
56
39
  res.appned(item.provider)
57
40
  return res
41
+
42
+
43
+ @abstractmethod
44
+ def _deploy(self, *args, **kwargs) -> Any:
45
+ """Any method to deploy targeting the customer"""
46
+
47
+
48
+ class Customer(BaseCustomer):
49
+ id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)
50
+ name: Optional[str] = Field(default=None, description="customer's name if any")
51
+ products: Optional[List[Product]] = Field(default=list, description="store products that the customer is associated with")
52
+ analysis: str = Field(default=None, description="store the latest analysis results on the customer")
53
+ status: str = Field(default=Status.ON_WORKFLOW)
@@ -1,22 +1,23 @@
1
1
  import uuid
2
+ from abc import ABC, abstractmethod
2
3
  from typing import Any, Dict, List, Callable, Type, Optional, get_args, get_origin
4
+
3
5
  from pydantic import UUID4, InstanceOf, BaseModel, ConfigDict, Field, create_model, field_validator, model_validator
4
6
  from pydantic_core import PydanticCustomError
5
7
 
8
+ from versionhq.tool import ComposioAppName
9
+
6
10
 
7
- class ProductProvider(BaseModel):
11
+ class ProductProvider(ABC, BaseModel):
8
12
  """
9
- Store the minimal client information.
10
- `data_pipeline` and `destinations` are for composio plug-in.
11
- (!REFINEME) Create an Enum list for the options.
12
- (!REFINEME) Create an Enum list for regions.
13
+ Abstract class for the product provider entity.
13
14
  """
14
15
 
15
16
  id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)
16
- name: Optional[str] = Field(default=None, description="client name")
17
+ name: Optional[str] = Field(default=None)
17
18
  region: Optional[str] = Field(default=None, description="region of client's main business operation")
18
- data_pipeline: Optional[List[str]] = Field(default=None, description="store the data pipelines that the client is using")
19
- destinations: Optional[List[str]] = Field(default=None,description="store the destination services that the client is using")
19
+ data_pipelines: Optional[List[ComposioAppName | str]] = Field(default_factory=list)
20
+ destination_services: Optional[List[ComposioAppName | str]] = Field(default=None)
20
21
 
21
22
  @field_validator("id", mode="before")
22
23
  @classmethod
@@ -2,6 +2,7 @@ import uuid
2
2
  from abc import ABC
3
3
  from datetime import date, datetime, time, timedelta
4
4
  from typing import Any, Dict, List, Callable, Type, Optional, get_args, get_origin
5
+ from typing_extensions import Self
5
6
  from pydantic import UUID4, InstanceOf, BaseModel, ConfigDict, Field, field_validator, model_validator
6
7
  from pydantic_core import PydanticCustomError
7
8
 
@@ -9,6 +10,7 @@ from versionhq.clients.product.model import Product
9
10
  from versionhq.clients.customer.model import Customer
10
11
  from versionhq.agent.model import Agent
11
12
  from versionhq.team.model import Team
13
+ from versionhq.tool import ComposioAppName
12
14
 
13
15
 
14
16
  class ScoreFormat:
@@ -56,14 +58,12 @@ class Score:
56
58
  class MessagingComponent(ABC, BaseModel):
57
59
  layer_id: int = Field(default=0, description="add id of the layer: 0, 1, 2")
58
60
  message: str = Field(default=None, max_length=1024, description="text message content to be sent")
59
- interval: Optional[str] = Field(
60
- default=None, description="interval to move on to the next layer. if this is the last layer, set as `None`"
61
- )
62
- score: float | InstanceOf[Score] = Field(default=None)
63
- condition: str = Field(default=None, max_length=128, description="condition to execute the next messaging component")
61
+ score: InstanceOf[Score] = Field(default=None)
62
+ condition: str = Field(default=None, max_length=128, description="condition to execute the next component")
63
+ interval: Optional[str] = Field(default=None, description="ideal interval to set to assess the condition")
64
64
 
65
65
 
66
- def store_scoring_result(self, scoring_subject: str, score_raw: int | Score | ScoreFormat = None):
66
+ def store_scoring_result(self, subject: str, score_raw: int | Score | ScoreFormat = None) -> Self:
67
67
  """
68
68
  Set up the `score` field
69
69
  """
@@ -73,12 +73,12 @@ class MessagingComponent(ABC, BaseModel):
73
73
 
74
74
  elif isinstance(score_raw, ScoreFormat):
75
75
  score_instance = Score()
76
- setattr(score_instance, scoring_subject, score_raw)
76
+ setattr(score_instance, subject, score_raw)
77
77
  setattr(self, "score", score_instance)
78
78
 
79
79
  elif isinstance(score_raw, int) or isinstance(score_raw, float):
80
80
  score_instance, score_format_instance = Score(), ScoreFormat(rate=score_raw, weight=1)
81
- setattr(score_instance, "kwargs", { scoring_subject: score_format_instance })
81
+ setattr(score_instance, "kwargs", { subject: score_format_instance })
82
82
  setattr(self, "score", score_instance)
83
83
 
84
84
  else:
@@ -99,23 +99,17 @@ class MessagingWorkflow(ABC, BaseModel):
99
99
  model_config = ConfigDict()
100
100
 
101
101
  id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)
102
- components: List[MessagingComponent] = Field(default_factory=list, description="store messaging components in the workflow")
102
+ messaging_components: List[MessagingComponent] = Field(default_factory=list, description="store messaging components in the workflow")
103
103
 
104
104
  # responsible tean or agents
105
- team: Optional[Team] = Field(default=None, description="store `Team` instance responsibile for autopiloting this workflow")
106
- agents: Optional[List[Agent]] = Field(
107
- default=None, description="store `Agent` instances responsible for autopiloting this workflow. if the team exsits, this field remains as `None`")
105
+ team: Optional[Team] = Field(default=None, description="store a responsibile team to autopilot the workflow")
106
+ agents: Optional[List[Agent]] = Field(default=None, description="store responsible agents. None when the team exists")
108
107
 
109
108
  # metrics
110
- destination: Optional[str | None] = Field(default=None, description="destination service to launch this workflow")
109
+ destination: Optional[ComposioAppName | str] = Field(default=None, description="destination service to launch the workflow")
111
110
  product: InstanceOf[Product] = Field(default=None)
112
111
  customer: InstanceOf[Customer] = Field(default=None)
113
-
114
- metrics: List[Dict[str, Any]] | List[str] = Field(
115
- default=None,
116
- max_length=256,
117
- description="store metrics that used to predict and track the performance of this workflow."
118
- )
112
+ performance_metrics: List[Dict[str, Any]] | List[str] = Field(default=None, max_length=256, description="performance metrics to track")
119
113
 
120
114
  @field_validator("id", mode="before")
121
115
  @classmethod
@@ -131,11 +125,11 @@ class MessagingWorkflow(ABC, BaseModel):
131
125
  Prioritize customer's destination to the product provider's destination list.
132
126
  """
133
127
  if self.destination is None:
134
- if self.customer is not None:
135
- self.destination = self.customer.on
128
+ # if self.customer is not None:
129
+ # self.destination = self.customer.on
136
130
 
137
- elif self.product.provider is not None and self.product.provider.destinations:
138
- self.destination = self.product.provider.destinations[0]
131
+ if self.product.provider is not None and self.product.provider.destination_services:
132
+ self.destination = self.product.provider.destination_services[0]
139
133
 
140
134
  return self
141
135
 
@@ -154,7 +148,7 @@ class MessagingWorkflow(ABC, BaseModel):
154
148
 
155
149
 
156
150
  @property
157
- def name(self):
151
+ def name(self) -> str:
158
152
  if self.customer.id:
159
153
  return f"Workflow ID: {self.id} - on {self.product.id} for {self.customer.id}"
160
154
  else: