versionhq 1.1.8.1__py3-none-any.whl → 1.1.9.1__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.
@@ -0,0 +1,149 @@
1
+ import os
2
+ import uuid
3
+ from dotenv import load_dotenv
4
+ from typing import Any, Callable, Type, get_args, get_origin, Optional, Tuple
5
+
6
+ from pydantic import BaseModel, Field, model_validator, field_validator, UUID4
7
+ from pydantic_core import PydanticCustomError
8
+
9
+ from composio import ComposioToolSet, Action, App, action
10
+
11
+ from versionhq.tool import ComposioAppName, ComposioAuthScheme, composio_app_set, COMPOSIO_STATUS
12
+
13
+ load_dotenv(override=True)
14
+
15
+ DEFAULT_REDIRECT_URL = os.environ.get("DEFAULT_REDIRECT_URL", None)
16
+ DEFAULT_USER_ID = os.environ.get("DEFAULT_USER_ID", None)
17
+
18
+
19
+ class Composio(BaseModel):
20
+ """
21
+ Class to handle composio tools.
22
+ """
23
+
24
+ id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)
25
+ app_name: str = Field(default=ComposioAppName.HUBSPOT)
26
+ user_id: str = Field(default=DEFAULT_USER_ID)
27
+ auth_scheme: str = Field(default=ComposioAuthScheme.OAUTH2)
28
+ redirect_url: str = Field(default=DEFAULT_REDIRECT_URL, description="redirect url after successful oauth2 connection")
29
+ connect_request_id: str = Field(default=None, description="store the client's composio id to connect with the app")
30
+
31
+ @property
32
+ def toolset(self) -> ComposioToolSet:
33
+ return ComposioToolSet(api_key=os.environ.get("COMPOSIO_API_KEY"))
34
+
35
+
36
+ def __name__(self):
37
+ return self.app_name
38
+
39
+
40
+ @field_validator("id", mode="before")
41
+ @classmethod
42
+ def _deny_user_set_id(cls, v: Optional[UUID4]) -> None:
43
+ if v:
44
+ raise PydanticCustomError("may_not_set_field", "This field is not to be set by the user.", {})
45
+
46
+
47
+ # @model_validator("user_id", mode="before")
48
+ # @classmethod
49
+ # def _deny_no_user_id(cls, v: Optional[str]) -> None:
50
+ # if v is None:
51
+ # raise PydanticCustomError("user_id_missing", "Need user_id to connect with the tool", {})
52
+
53
+
54
+ @model_validator(mode="after")
55
+ def validate_app_name(self):
56
+ if self.app_name not in ComposioAppName:
57
+ raise PydanticCustomError("no_app_name", f"The app name {self.app_name} is not valid.", {})
58
+
59
+ return self
60
+
61
+
62
+ @model_validator(mode="after")
63
+ def validate_auth_scheme(self):
64
+ """
65
+ Raise error when the client uses auth scheme unavailable for the app.
66
+ """
67
+ app_set = next(filter(lambda tup: self.app_name in tup, composio_app_set), None)
68
+ if not app_set:
69
+ raise PydanticCustomError("no_app_set", f"The app set of {self.app_name} is missing.", {})
70
+
71
+ else:
72
+ acceptable_auth_scheme = next(filter(lambda item: self.auth_scheme in item, app_set), None)
73
+ if acceptable_auth_scheme is None:
74
+ raise PydanticCustomError("invalid_auth_scheme", f"The app {self.app_name} must have different auth_scheme.", {})
75
+
76
+ return self
77
+
78
+
79
+ # connect with composio to use the tool
80
+ def connect(self, token: Optional[str] = None, api_key: Optional[str] = None) -> Tuple[str | Any]:
81
+ """
82
+ Connect with Composio, retrieve `connect_request_id`, and validate the connection.
83
+ """
84
+
85
+ if not self.user_id:
86
+ raise PydanticCustomError("user_id_missing", "Need user_id to connect with the tool", {})
87
+
88
+
89
+ connection_request, connected_account = None, None
90
+
91
+ if self.auth_scheme == ComposioAuthScheme.API_KEY:
92
+ collected_from_user = {}
93
+ collected_from_user["api_key"] = api_key
94
+ connection_request = self.toolset.initiate_connection(
95
+ connected_account_params = collected_from_user,
96
+ app=self.app_name,
97
+ entity_id=self.user_id,
98
+ auth_scheme=self.auth_scheme,
99
+ )
100
+
101
+ if self.auth_scheme == ComposioAuthScheme.BEARER_TOKEN:
102
+ collected_from_user = {}
103
+ collected_from_user["token"] = token
104
+ connection_request = self.toolset.initiate_connection(
105
+ connected_account_params = collected_from_user,
106
+ app=self.app_name,
107
+ entity_id=self.user_id,
108
+ auth_scheme=self.auth_scheme,
109
+ )
110
+
111
+ if self.auth_scheme == ComposioAuthScheme.OAUTH2:
112
+ connection_request = self.toolset.initiate_connection(
113
+ app=self.app_name,
114
+ redirect_url = self.redirect_url, # clients will be redirected to this url after successful auth.
115
+ entity_id=self.user_id,
116
+ auth_scheme=self.auth_scheme,
117
+ )
118
+
119
+ # connection_request.wait_until_active(self.toolset.client, timeout=60)
120
+
121
+ if connection_request.connectionStatus is not COMPOSIO_STATUS.FAILED:
122
+ self.connect_request_id = connection_request.connectedAccountId
123
+ connected_account = self.toolset.get_connected_account(id=self.connect_request_id)
124
+
125
+ if connected_account.status is not COMPOSIO_STATUS.FAILED:
126
+ setattr(self.toolset, "entity_id", self.user_id)
127
+
128
+ return connected_account, connected_account.status if connected_account else connection_request.connectionStatus
129
+
130
+
131
+
132
+
133
+ # @action(toolname=ComposioAppName.HUBSPOT)
134
+ # def deploy(self, param1: str, param2: str, execute_request: Callable) -> str:
135
+ # """
136
+ # Define custom actions
137
+ # my custom action description which will be passed to llm
138
+
139
+ # :param param1: param1 description which will be passed to llm
140
+ # :param param2: param2 description which will be passed to llm
141
+ # :return info: return description
142
+ # """
143
+
144
+ # response = execute_request(
145
+ # "/my_action_endpoint",
146
+ # "GET",
147
+ # {} # body can be added here
148
+ # ) # execute requests by appending credentials to the request
149
+ # return str(response) # complete auth dict is available for local use if needed
@@ -1,5 +1,6 @@
1
1
  from typing import Callable
2
2
  from pydantic import BaseModel
3
+
3
4
  from versionhq.tool.model import Tool
4
5
 
5
6
 
@@ -13,6 +14,7 @@ def tool(*args):
13
14
  def _make_tool(f: Callable) -> Tool:
14
15
  if f.__doc__ is None:
15
16
  raise ValueError("Function must have a docstring")
17
+
16
18
  if f.__annotations__ is None:
17
19
  raise ValueError("Function must have type annotations")
18
20
 
@@ -26,7 +28,7 @@ def tool(*args):
26
28
  },
27
29
  },
28
30
  )
29
- return Tool(name=tool_name, func=f, args_schema=args_schema)
31
+ return Tool(name=tool_name, function=f, args_schema=args_schema)
30
32
 
31
33
  return _make_tool
32
34
 
versionhq/tool/model.py CHANGED
@@ -1,63 +1,69 @@
1
- from abc import ABC
1
+ from abc import ABC, abstractmethod
2
2
  from inspect import signature
3
3
  from typing import Any, Dict, Callable, Type, Optional, get_args, get_origin
4
- from pydantic import InstanceOf, BaseModel, ConfigDict, Field, create_model, field_validator, model_validator
4
+ from typing_extensions import Self
5
+ from pydantic import InstanceOf, BaseModel, ConfigDict, Field, field_validator, model_validator
5
6
 
6
7
  from versionhq._utils.cache_handler import CacheHandler
7
8
 
8
9
 
9
- class Tool(ABC, BaseModel):
10
+ class BaseTool(ABC, BaseModel):
10
11
  """
11
- The function that will be executed when the tool is called.
12
+ Abstract class for Tool class.
12
13
  """
13
14
 
14
- class ArgsSchema(BaseModel):
15
+ class _ArgsSchemaPlaceholder(BaseModel):
15
16
  pass
16
17
 
17
- model_config = ConfigDict()
18
- name: str = Field(default=None)
19
- func: Callable = Field(default=None)
20
- cache_function: Callable = lambda _args=None, _result=None: True
21
- args_schema: Type[BaseModel] = Field(default_factory=ArgsSchema)
22
- tool_handler: Optional[Dict[str, Any]] = Field(
23
- default=None,
24
- description="store tool_handler to record the usage of this tool. to avoid circular import, set as Dict format",
25
- )
26
-
27
- @property
28
- def description(self):
29
- args_schema = {
30
- name: { "description": field.description, "type": Tool._get_arg_annotations(field.annotation) }
31
- for name, field in self.args_schema.model_fields.items()
32
- }
33
- return f"Tool Name: {self.name}\nTool Arguments: {args_schema}\nTool Description: {self.description}"
18
+ args_schema: Type[BaseModel] = Field(default_factory=_ArgsSchemaPlaceholder)
34
19
 
35
20
 
36
21
  @field_validator("args_schema", mode="before")
37
22
  @classmethod
38
23
  def _default_args_schema(cls, v: Type[BaseModel]) -> Type[BaseModel]:
39
- if not isinstance(v, cls.ArgsSchema):
24
+ if not isinstance(v, cls._ArgsSchemaPlaceholder):
40
25
  return v
41
26
 
42
27
  return type(
43
28
  f"{cls.__name__}Schema",
44
29
  (BaseModel,),
45
- {
46
- "__annotations__": {
47
- k: v for k, v in cls._run.__annotations__.items() if k != "return"
48
- },
49
- },
30
+ { "__annotations__": { k: v for k, v in cls._run.__annotations__.items() if k != "return" }},
50
31
  )
51
32
 
33
+
34
+ @abstractmethod
35
+ def _run(self, *args: Any, **kwargs: Any,) -> Any:
36
+ """any handling"""
37
+
38
+
39
+
40
+ class Tool(BaseTool):
41
+ name: str = Field(default=None)
42
+ goal: str = Field(default=None)
43
+ function: Callable = Field(default=None)
44
+ cache_function: Callable = lambda _args=None, _result=None: True
45
+ tool_handler: Optional[Dict[str, Any]] = Field(
46
+ default=None,
47
+ description="store tool_handler to record the usage of this tool. to avoid circular import, set as Dict format",
48
+ )
49
+
52
50
  @model_validator(mode="after")
53
- def set_up_tool_handler_instance(self):
51
+ def set_up_tool_handler(self) -> Self:
54
52
  from versionhq.tool.tool_handler import ToolHandler
55
53
 
56
54
  if self.tool_handler:
57
55
  ToolHandler(**self.tool_handler)
56
+ return self
57
+
58
58
 
59
+ @model_validator(mode="after")
60
+ def set_up_function(self) -> Self:
61
+ if self.function is None:
62
+ self.function = self._run
63
+ self._set_args_schema_from_func()
59
64
  return self
60
65
 
66
+
61
67
  @staticmethod
62
68
  def _get_arg_annotations(annotation: type[Any] | None) -> str:
63
69
  if annotation is None:
@@ -67,11 +73,7 @@ class Tool(ABC, BaseModel):
67
73
  args = get_args(annotation)
68
74
 
69
75
  if origin is None:
70
- return (
71
- annotation.__name__
72
- if hasattr(annotation, "__name__")
73
- else str(annotation)
74
- )
76
+ return annotation.__name__ if hasattr(annotation, "__name__") else str(annotation)
75
77
 
76
78
  if args:
77
79
  args_str = ", ".join(Tool._get_arg_annotations(arg) for arg in args)
@@ -79,112 +81,133 @@ class Tool(ABC, BaseModel):
79
81
 
80
82
  return origin.__name__
81
83
 
82
- def _set_args_schema(self):
83
- if self.args_schema is None:
84
- class_name = f"{self.__class__.__name__}Schema"
85
-
86
- self.args_schema = type(
87
- class_name,
88
- (BaseModel,),
89
- {
90
- "__annotations__": {
91
- k: v
92
- for k, v in self._run.__annotations__.items()
93
- if k != "return"
94
- },
95
- },
96
- )
97
84
 
98
- @classmethod
99
- def from_composio(
100
- cls, func: Callable = None, tool_name: str = "Composio tool"
101
- ) -> "Tool":
85
+ def _parse_args(self, raw_args: str | dict) -> dict:
102
86
  """
103
- Create a Pydantic BaseModel instance from Composio tools, ensuring the Tool instance has a func to be executed.
104
- Refer to the `args_schema` from the func signature if any. Else, create an `args_schema`.
87
+ Parse and validate the input arguments against the schema
105
88
  """
89
+ if isinstance(raw_args, str):
90
+ try:
91
+ import json
92
+ raw_args = json.loads(raw_args)
93
+ except json.JSONDecodeError as e:
94
+ raise ValueError(f"Failed to parse arguments as JSON: {e}")
106
95
 
107
- if not func:
108
- raise ValueError("Params must have a callable 'func' attribute.")
109
-
110
- # args_schema = getattr(tool, "args_schema", None)
111
- args_fields = {}
112
- func_signature = signature(func)
113
- annotations = func_signature.parameters
114
- for name, param in annotations.items():
115
- if name != "self":
116
- param_annotation = (
117
- param.annotation if param.annotation != param.empty else Any
118
- )
119
- field_info = Field(default=..., description="")
120
- args_fields[name] = (param_annotation, field_info)
121
-
122
- args_schema = (
123
- create_model(f"{tool_name}Input", **args_fields)
124
- if args_fields
125
- else create_model(f"{tool_name}Input", __base__=BaseModel)
96
+ try:
97
+ validated_args = self.args_schema.model_validate(raw_args)
98
+ return validated_args.model_dump()
99
+
100
+ except Exception as e:
101
+ raise ValueError(f"Arguments validation failed: {e}")
102
+
103
+
104
+ def _set_args_schema_from_func(self):
105
+ class_name = f"{self.__class__.__name__}Schema"
106
+ self.args_schema = type(
107
+ class_name,
108
+ (BaseModel,),
109
+ { "__annotations__": {
110
+ k: v for k, v in self._run.__annotations__.items() if k != "return"
111
+ } },
126
112
  )
113
+ return self
114
+
127
115
 
128
- return cls(name=tool_name, func=func, args_schema=args_schema)
116
+ def _run(self, *args: Any, **kwargs: Any) -> Any:
117
+ return self.run(*args, **kwargs)
129
118
 
130
119
 
131
120
  def run(self, *args, **kwargs) -> Any:
132
121
  """
133
- Use the tool.
134
- When the tool has a func, execute the func and return any response from the func.
135
- Else,
136
-
137
- The response will be cascaded to the Task and stored in the TaskOutput.
122
+ Use tool
138
123
  """
124
+ from versionhq.tool.tool_handler import ToolHandler
125
+
126
+ if self.function:
127
+ return self.function(*args, **kwargs)
139
128
 
140
129
  result = None
130
+ acceptable_args = self.args_schema.model_json_schema()["properties"].keys()
131
+ acceptable_kwargs = { k: v for k, v in kwargs.items() if k in acceptable_args }
132
+ tool_called = ToolSet(tool=self, kwargs=acceptable_kwargs)
133
+
134
+ if self.tool_handler:
135
+ if self.tool_handler.has_called_before(tool_called):
136
+ self.tool_handler.error = "Agent execution error"
141
137
 
142
- if self.func is not None:
143
- result = self.func(
144
- *args, **kwargs
145
- ) #! REFINEME - format - json dict, pydantic, raw
138
+ elif self.tool_handler.cache:
139
+ result = self.tools_handler.cache.read(tool=tool_called.tool.name, input=tool_called.kwargs)
140
+ if result is None:
141
+ parsed_kwargs = self._parse_args(raw_args=acceptable_kwargs)
142
+ result = self.function(**parsed_kwargs) if self.function else None
146
143
 
147
144
  else:
148
- acceptable_args = self.args_schema.model_json_schema()["properties"].keys()
149
- arguments = {k: v for k, v in kwargs.items() if k in acceptable_args}
150
- tool_called = ToolCalled(tool=self, arguments=arguments)
151
-
152
- if self.tool_handler:
153
- if self.tool_handler.has_called_before(tool_called):
154
- self.tool_handler.error = "Agent execution error."
155
-
156
- elif self.tool_handler.cache:
157
- result = self.tools_handler.cache.read(
158
- tool=tool_called.tool.name, input=tool_called.arguments
159
- )
160
- # from_cache = result is not None
161
- if result is None:
162
- result = self.invoke(input=arguments)
163
-
164
- else:
165
- from versionhq.tool.tool_handler import ToolHandler
166
-
167
- tool_handler = ToolHandler(
168
- last_used_tool=tool_called, cache=CacheHandler()
169
- )
170
- self.tool_handler = tool_handler
171
- result = self.invoke(input=arguments)
145
+ tool_handler = ToolHandler(last_used_tool=tool_called, cache_handler=CacheHandler())
146
+ self.tool_handler = tool_handler
147
+ parsed_kwargs = self._parse_args(raw_args=acceptable_kwargs)
148
+ result = self.function(**parsed_kwargs) if self.function else None
172
149
 
173
150
  return result
174
151
 
175
152
 
176
- class ToolCalled(BaseModel):
153
+ @property
154
+ def description(self) -> str:
155
+ args_schema = {
156
+ name: {
157
+ "description": field.description,
158
+ "type": self._get_arg_annotations(field.annotation),
159
+ }
160
+ for name, field in self.args_schema.model_fields.items()
161
+ }
162
+
163
+ return f"Tool Name: {self.name}\nTool Arguments: {args_schema}\nGoal: {self.goal}"
164
+
165
+
166
+
167
+ # @classmethod
168
+ # def from_composio(
169
+ # cls, func: Callable = None, tool_name: str = "Composio tool"
170
+ # ) -> "Tool":
171
+ # """
172
+ # Create Tool from the composio tool, ensuring the Tool instance has a func to be executed.
173
+ # Refer to the `args_schema` from the func signature if any. Else, create an `args_schema`.
174
+ # """
175
+
176
+ # if not func:
177
+ # raise ValueError("Params must have a callable 'function' attribute.")
178
+
179
+ # # args_schema = getattr(tool, "args_schema", None)
180
+ # args_fields = {}
181
+ # func_signature = signature(func)
182
+ # annotations = func_signature.parameters
183
+ # for name, param in annotations.items():
184
+ # if name != "self":
185
+ # param_annotation = (
186
+ # param.annotation if param.annotation != param.empty else Any
187
+ # )
188
+ # field_info = Field(default=..., description="")
189
+ # args_fields[name] = (param_annotation, field_info)
190
+
191
+ # args_schema = (
192
+ # create_model(f"{tool_name}Input", **args_fields)
193
+ # if args_fields
194
+ # else create_model(f"{tool_name}Input", __base__=BaseModel)
195
+ # )
196
+
197
+ # return cls(name=tool_name, func=func, args_schema=args_schema)
198
+
199
+
200
+ class ToolSet(BaseModel):
177
201
  """
178
202
  Store the tool called and any kwargs used.
179
203
  """
180
-
181
- tool: InstanceOf[Tool] = Field(..., description="store the tool instance to be called.")
182
- arguments: Optional[Dict[str, Any]] = Field(..., description="kwargs passed to the tool")
204
+ tool: InstanceOf[Tool] | Any = Field(..., description="store the tool instance to be called.")
205
+ kwargs: Optional[Dict[str, Any]] = Field(..., description="kwargs passed to the tool")
183
206
 
184
207
 
185
- class InstructorToolCalled(BaseModel):
186
- tool: InstanceOf[Tool] = Field(..., description="store the tool instance to be called.")
187
- arguments: Optional[Dict[str, Any]] = Field(..., description="kwargs passed to the tool")
208
+ class InstructorToolSet(BaseModel):
209
+ tool: InstanceOf[Tool] | Any = Field(..., description="store the tool instance to be called.")
210
+ kwargs: Optional[Dict[str, Any]] = Field(..., description="kwargs passed to the tool")
188
211
 
189
212
 
190
213
  class CacheTool(BaseModel):
@@ -1,48 +1,45 @@
1
- from typing import Any, Optional
1
+ from typing import Optional, Any
2
2
  from pydantic import InstanceOf
3
- from versionhq.tool.model import ToolCalled, InstructorToolCalled, CacheTool
3
+
4
+ from versionhq.tool.model import ToolSet, InstructorToolSet
4
5
  from versionhq._utils.cache_handler import CacheHandler
5
6
 
6
7
 
7
8
  class ToolHandler:
8
9
  """
9
- Record the tool usage by ToolCalled instance with cache and error recording.
10
- Use as a callback function.
10
+ Record the tool usage by ToolSet instance with cache and error recording.
11
11
  """
12
12
 
13
- last_used_tool: ToolCalled = {}
13
+ last_used_tool: InstanceOf[ToolSet] | InstanceOf[InstructorToolSet]
14
14
  cache: Optional[CacheHandler]
15
15
  error: Optional[str]
16
16
 
17
- def __init__(self, cache_handler: Optional[CacheHandler] = None):
18
- """
19
- Initialize the callback handler.
20
- """
21
-
17
+ def __init__(
18
+ self,
19
+ last_used_tool: InstanceOf[ToolSet] | InstanceOf[InstructorToolSet] = None,
20
+ cache_handler: Optional[CacheHandler] = None
21
+ ):
22
22
  self.cache = cache_handler
23
- self.last_used_tool = {}
23
+ self.last_used_tool = last_used_tool
24
+
24
25
 
25
26
  def record_last_tool_used(
26
27
  self,
27
- last_used_tool: InstanceOf[ToolCalled] | InstanceOf[InstructorToolCalled],
28
+ last_used_tool: InstanceOf[ToolSet] | InstanceOf[InstructorToolSet],
28
29
  output: str,
29
30
  should_cache: bool = True,
30
31
  ) -> Any:
32
+
31
33
  self.last_used_tool = last_used_tool
32
34
 
33
- if self.cache and should_cache and last_used_tool.tool_name != CacheTool().name:
34
- self.cache.add(
35
- last_used_tool.tool_name,
36
- input.last_used_tool.arguments,
37
- output=output,
38
- )
35
+ from versionhq.tool.model import CacheTool
36
+ if self.cache and should_cache and last_used_tool.tool.name != CacheTool().name:
37
+ self.cache.add(tool=last_used_tool.tool.name, input=last_used_tool.kwargs, output=output)
38
+
39
39
 
40
- def has_called_before(self, tool_called: ToolCalled = None) -> bool:
40
+ def has_called_before(self, tool_called: ToolSet = None) -> bool:
41
41
  if tool_called is None or not self.last_used_tool:
42
42
  return False
43
43
 
44
44
  if tool_called := self.last_used_tool:
45
- return bool(
46
- (tool_called.tool.name == self.last_used_tool.tool.name)
47
- and (tool_called.arguments == self.last_used_tool.arguments)
48
- )
45
+ return bool((tool_called.tool.name == self.last_used_tool.tool.name) and (tool_called.kwargs == self.last_used_tool.kwargs))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: versionhq
3
- Version: 1.1.8.1
3
+ Version: 1.1.9.1
4
4
  Summary: LLM orchestration frameworks for model-agnostic AI agents that handle complex outbound workflows
5
5
  Author-email: Kuriko Iwai <kuriko@versi0n.io>
6
6
  License: MIT License
@@ -312,7 +312,7 @@ src/
312
312
  4. Test the features using the `tests` directory.
313
313
 
314
314
  - Add a test function to respective components in the `tests` directory.
315
- - Add your `LITELLM_API_KEY` and `OPENAI_API_KEY` to the Github `repository secrets` @ settings > secrets & variables > Actions.
315
+ - Add your `LITELLM_API_KEY`, `OPENAI_API_KEY`, `COMPOSIO_API_KEY`, `DEFAULT_USER_ID` to the Github `repository secrets` @ settings > secrets & variables > Actions.
316
316
  - Run a test.
317
317
  ```
318
318
  uv run pytest tests -vv
@@ -1,24 +1,24 @@
1
- versionhq/__init__.py,sha256=vDnsppEwUlpBHeAcl8jCKzt8SaGylbfIND1PjgjY2s8,871
1
+ versionhq/__init__.py,sha256=HIOFr73z0KeJs9qFVvW1DjRFj7JyiJcRGGxylbQT_bQ,931
2
2
  versionhq/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- versionhq/_utils/cache_handler.py,sha256=zDQKzIn7vp-M2-uepHFxgJstjfftZS5mzXKL_-4uVvI,370
3
+ versionhq/_utils/cache_handler.py,sha256=3-lw_5ZMWC8hnPAkSQULJ2V1FvZZ-wg9mQaUJGSOjI8,403
4
4
  versionhq/_utils/i18n.py,sha256=TwA_PnYfDLA6VqlUDPuybdV9lgi3Frh_ASsb_X8jJo8,1483
5
5
  versionhq/_utils/logger.py,sha256=lqRYH45KHMQ4mwE1woa5xNmngYu4O749AYECsnWWpmA,1851
6
6
  versionhq/_utils/process_config.py,sha256=UqoWD5IR4VLxEDGxIyVUylw_ppXwk8Wx1ynVuD-pUSg,822
7
- versionhq/_utils/rpm_controller.py,sha256=T7waIGeblu5K58erY4lqVLcPsWM7W9UFdU3DG9Dsk0w,2214
8
- versionhq/_utils/usage_metrics.py,sha256=c33a_28y8ECUgflsKN3mkNm0fNkWgZmXwybMwIqoKXA,1098
7
+ versionhq/_utils/rpm_controller.py,sha256=dUgFd6JtdjiLLTRmrjsBHdTaLn73XFuKpLbJh7thf2A,2289
8
+ versionhq/_utils/usage_metrics.py,sha256=hhq1OCW8Z4V93vwW2O2j528EyjOlF8wlTsX5IL-7asA,1106
9
9
  versionhq/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- versionhq/agent/model.py,sha256=tv14XkjrgsFsryFWzaw0w2h0X1T0ffipVK9l4kYbpIE,18598
11
- versionhq/agent/parser.py,sha256=db5kfk-lR1Ph9-rsTvSeW1NjR6GJ00iaqTNYxJy3N8o,5487
10
+ versionhq/agent/model.py,sha256=8QtZfbeys9cCujc4whKfXdoP0aQKMuvL2qN8WQmugew,19152
11
+ versionhq/agent/parser.py,sha256=Z_swUPO3piJQuYU8oVYwXWeR2zjmNb4PxbXZeR-GlIg,4694
12
12
  versionhq/agent/TEMPLATES/Backstory.py,sha256=cdngBx1GEv7nroR46FEhnysnBJ9mEVL763_9np6Skkc,395
13
13
  versionhq/agent/TEMPLATES/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  versionhq/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  versionhq/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  versionhq/clients/customer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- versionhq/clients/customer/model.py,sha256=rQnCv_wdCdrYAsUjyB6X6ULiuWfqcBBoarXcQT5kj88,1762
17
+ versionhq/clients/customer/model.py,sha256=ruxqSvjBHrSJnNq9Jj5Ko1CW6l8RLiPzhbC_F7tbOnM,1670
18
18
  versionhq/clients/product/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  versionhq/clients/product/model.py,sha256=HxiSv8zq5L0H210jXWfjX_Yg1oyWhi2YASR68JEtmDY,2408
20
20
  versionhq/clients/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- versionhq/clients/workflow/model.py,sha256=YI6sNpdbizUOqPPXrTCtdmVt619uQ5hQgGS0BcA0njI,5834
21
+ versionhq/clients/workflow/model.py,sha256=LPet39sK7vUpBQ1mymdNX1xUPseGWv_5W7je_7sif_M,5883
22
22
  versionhq/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  versionhq/llm/llm_vars.py,sha256=YZoXqFBW7XpclUZ14_AAz7WOjoyCXnGcI959GSpX2q0,5343
24
24
  versionhq/llm/model.py,sha256=mXzSuf1s6MebGT7_yqgNppde0NIlAF8bjIXAp2MZ9Uw,8247
@@ -27,16 +27,17 @@ versionhq/storage/task_output_storage.py,sha256=xoBJHeqUyQt6iJoR1WQTghP-fyxXL66q
27
27
  versionhq/task/__init__.py,sha256=g4mCATnn1mUXxsfQ5p6IpPawr8O421wVIT8kMKEcxQw,180
28
28
  versionhq/task/formatter.py,sha256=N8Kmk9vtrMtBdgJ8J7RmlKNMdZWSmV8O1bDexmCWgU0,643
29
29
  versionhq/task/log_handler.py,sha256=KJRrcNZgFSKhlNzvtYFnvtp6xukaF1s7ifX9u4zWrN8,1683
30
- versionhq/task/model.py,sha256=F6yd8oPJ6cjH0PcGZru7eska7Qu6lEtMDyjgn-ZnAfE,19394
30
+ versionhq/task/model.py,sha256=EbgYHLNq8l1zfRDnF-yEcuSZ0aNvzbRmHYgfVyJq84c,19910
31
31
  versionhq/team/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- versionhq/team/model.py,sha256=Liq0PUHncZAJyjjmqOL5mmt5E0Z0dBfhTmtRjUZQWiE,20369
32
+ versionhq/team/model.py,sha256=E52OUVzUtvR--51SFRJos3JdYKri1t2jbvvzoOvShQc,20181
33
33
  versionhq/team/team_planner.py,sha256=uzX2yed7A7gNSs6qH5jIq2zXMVF5BwQQ4HPATsB9DSQ,3675
34
- versionhq/tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- versionhq/tool/decorator.py,sha256=Y-j4jkoujD5LUvpe8uf3p5Zagk2XVaRKC9rkIE-2geo,1189
36
- versionhq/tool/model.py,sha256=GjhQdlAyl2MGu4iiiFW7LqBWaaXhdlRQz2OGHhmr9FM,6828
37
- versionhq/tool/tool_handler.py,sha256=esUqGp8HoREesai8fmh2klAf04Sjpsacmb03C7F6sNQ,1541
38
- versionhq-1.1.8.1.dist-info/LICENSE,sha256=7CCXuMrAjPVsUvZrsBq9DsxI2rLDUSYXR_qj4yO_ZII,1077
39
- versionhq-1.1.8.1.dist-info/METADATA,sha256=7_hZDC_4H87AwyP_TtICbEv0XB_9DtUNI-80xjqqSBU,15919
40
- versionhq-1.1.8.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
41
- versionhq-1.1.8.1.dist-info/top_level.txt,sha256=DClQwxDWqIUGeRJkA8vBlgeNsYZs4_nJWMonzFt5Wj0,10
42
- versionhq-1.1.8.1.dist-info/RECORD,,
34
+ versionhq/tool/__init__.py,sha256=oU2Y84b7vywWq1xmFaBdXdH8Y9lGv7dmk2LEcj4dL-s,1692
35
+ versionhq/tool/composio.py,sha256=e-Vfr-eFm0ipiOerB_zAC1Sl90A39OD_k4QqgszWXWQ,5779
36
+ versionhq/tool/decorator.py,sha256=W_WjzZy8y43AoiFjHLPUQfNipmpOPe-wQknCWloPwmY,1195
37
+ versionhq/tool/model.py,sha256=8A1x8gEdTuP5teUf6o3VqJhrPI5m-XBoBXxgHiWCKcI,7499
38
+ versionhq/tool/tool_handler.py,sha256=rmm8snegwug4jl0Sbi_CteFajkbPAZ5koTQWDMwcIrQ,1510
39
+ versionhq-1.1.9.1.dist-info/LICENSE,sha256=7CCXuMrAjPVsUvZrsBq9DsxI2rLDUSYXR_qj4yO_ZII,1077
40
+ versionhq-1.1.9.1.dist-info/METADATA,sha256=-mFMCnD5q2XGVgaNyE8ddBpX8tgAR4sqlJ-Cmm0hBQA,15955
41
+ versionhq-1.1.9.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
42
+ versionhq-1.1.9.1.dist-info/top_level.txt,sha256=DClQwxDWqIUGeRJkA8vBlgeNsYZs4_nJWMonzFt5Wj0,10
43
+ versionhq-1.1.9.1.dist-info/RECORD,,