versionhq 1.2.1.18__py3-none-any.whl → 1.2.1.20__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
@@ -31,7 +31,7 @@ from versionhq.agent_network.formation import form_agent_network
31
31
  from versionhq.task_graph.draft import workflow
32
32
 
33
33
 
34
- __version__ = "1.2.1.18"
34
+ __version__ = "1.2.1.20"
35
35
  __all__ = [
36
36
  "Agent",
37
37
 
@@ -44,6 +44,7 @@ class Logger(BaseModel):
44
44
 
45
45
  verbose: bool = Field(default=True)
46
46
  info_file_save: bool = Field(default=False, description="whether to save INFO logs")
47
+ filename: str = Field(default=None)
47
48
  _printer: Printer = PrivateAttr(default_factory=Printer)
48
49
 
49
50
 
@@ -52,7 +53,7 @@ class Logger(BaseModel):
52
53
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
53
54
  self._printer.print(f"\n{timestamp} - versionHQ [{level.upper()}]: {message}", color=color)
54
55
 
55
- self._save(level=level, message=message)
56
+ self._save(level=level, message=message, filename=self.filename)
56
57
 
57
58
 
58
59
  def _save(self, level: str, message: str, filename: str = None):
@@ -74,7 +75,7 @@ class Logger(BaseModel):
74
75
  cwd = Path.cwd()
75
76
  log_file_dir = f"{cwd}/.logs"
76
77
  os.makedirs(log_file_dir, exist_ok=True)
77
- filename = filename if filename else datetime.now().strftime('%H_%M_%S_%d_%m_%Y')
78
+ filename = filename if filename else self.filename if self.filename else datetime.now().strftime('%H_%M_%S_%d_%m_%Y')
78
79
  abs_dir = f"{log_file_dir}/{filename}.log"
79
80
 
80
81
  logging.basicConfig(filename=abs_dir, filemode='w', level=logging_level)
versionhq/agent/model.py CHANGED
@@ -64,6 +64,7 @@ class Agent(BaseModel):
64
64
  _request_within_rpm_limit: Any = PrivateAttr(default=None)
65
65
  _token_process: TokenProcess = PrivateAttr(default_factory=TokenProcess)
66
66
  _times_executed: int = PrivateAttr(default=0)
67
+ _logger_config: Dict[str, Any] = PrivateAttr(default=dict(verbose=True, info_file_save=True))
67
68
  config: Optional[Dict[str, Any]] = Field(default=None, exclude=True, description="values to add to the Agent class")
68
69
 
69
70
  id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)
@@ -172,7 +173,7 @@ class Agent(BaseModel):
172
173
  tool_list.append(item)
173
174
 
174
175
  else:
175
- Logger().log(level="error", message=f"Tool {str(item)} is missing a function.", color="red")
176
+ Logger(**self.loger_config, filename=self.key).log(level="error", message=f"Tool {str(item)} is missing a function.", color="red")
176
177
  raise PydanticCustomError("invalid_tool", f"The tool {str(item)} is missing a function.", {})
177
178
 
178
179
  self.tools = tool_list
@@ -222,7 +223,7 @@ class Agent(BaseModel):
222
223
 
223
224
  if self.knowledge_sources:
224
225
  try:
225
- collection_name = f"{self.role.replace(' ', '_')}"
226
+ collection_name = self.key
226
227
  knowledge_sources = []
227
228
  docling_fp, txt_fp, json_fp, excel_fp, csv_fp, pdf_fp = [], [], [], [], [], []
228
229
  str_cont = ""
@@ -256,7 +257,7 @@ class Agent(BaseModel):
256
257
  self._knowledge = Knowledge(sources=knowledge_sources, embedder_config=self.embedder_config, collection_name=collection_name)
257
258
 
258
259
  except:
259
- Logger().log(level="warning", message="We cannot find the format for the source. Add BaseKnowledgeSource objects instead.", color="yellow")
260
+ Logger(**self._logger_config, filename=self.key).log(level="warning", message="We cannot find the format for the source. Add BaseKnowledgeSource objects instead.", color="yellow")
260
261
 
261
262
  return self
262
263
 
@@ -375,7 +376,7 @@ class Agent(BaseModel):
375
376
  """
376
377
 
377
378
  if not llm and not llm_config:
378
- Logger().log(level="error", message="Missing llm or llm_config values to update", color="red")
379
+ Logger(**self._logger_config, filename=self.key).log(level="error", message="Missing llm or llm_config values to update", color="red")
379
380
  pass
380
381
 
381
382
  self.llm = llm
@@ -423,7 +424,7 @@ class Agent(BaseModel):
423
424
  if self._rpm_controller and self.max_rpm:
424
425
  self._rpm_controller.check_or_wait()
425
426
 
426
- Logger().log(level="info", message=f"Messages sent to the model: {messages}", color="blue")
427
+ Logger(**self._logger_config, filename=self.key).log(level="info", message=f"Messages sent to the model: {messages}", color="blue")
427
428
 
428
429
  if tool_res_as_final:
429
430
  raw_response = self.func_calling_llm.call(messages=messages, tools=tools, tool_res_as_final=True)
@@ -433,11 +434,11 @@ class Agent(BaseModel):
433
434
  task.tokens = self.llm._tokens
434
435
 
435
436
  task_execution_counter += 1
436
- Logger().log(level="info", message=f"Agent response: {raw_response}", color="green")
437
+ Logger(**self._logger_config, filename=self.key).log(level="info", message=f"Agent response: {raw_response}", color="green")
437
438
  return raw_response
438
439
 
439
440
  except Exception as e:
440
- Logger().log(level="error", message=f"An error occured. The agent will retry: {str(e)}", color="red")
441
+ Logger(**self._logger_config, filename=self.key).log(level="error", message=f"An error occured. The agent will retry: {str(e)}", color="red")
441
442
 
442
443
  while not raw_response and task_execution_counter <= self.max_retry_limit:
443
444
  while (not raw_response or raw_response == "" or raw_response is None) and iterations < self.maxit:
@@ -449,11 +450,11 @@ class Agent(BaseModel):
449
450
  iterations += 1
450
451
 
451
452
  task_execution_counter += 1
452
- Logger().log(level="info", message=f"Agent #{task_execution_counter} response: {raw_response}", color="green")
453
+ Logger(**self._logger_config, filename=self.key).log(level="info", message=f"Agent #{task_execution_counter} response: {raw_response}", color="green")
453
454
  return raw_response
454
455
 
455
456
  if not raw_response:
456
- Logger().log(level="error", message="Received None or empty response from the model", color="red")
457
+ Logger(**self._logger_config, filename=self.key).log(level="error", message="Received None or empty response from the model", color="red")
457
458
  raise ValueError("Invalid response from LLM call - None or empty.")
458
459
 
459
460
 
@@ -463,7 +464,7 @@ class Agent(BaseModel):
463
464
  """
464
465
 
465
466
  if not kwargs:
466
- Logger().log(level="error", message="Missing values to update", color="red")
467
+ Logger(**self._logger_config, filename=self.key).log(level="error", message="Missing values to update", color="red")
467
468
  return self
468
469
 
469
470
  for k, v in kwargs.items():
@@ -503,7 +504,7 @@ class Agent(BaseModel):
503
504
  try:
504
505
  setattr(self, k, v)
505
506
  except Exception as e:
506
- Logger().log(level="error", message=f"Failed to update the field: {k} We'll skip it. Error: {str(e)}", color="red")
507
+ Logger(**self._logger_config, filename=self.key).log(level="error", message=f"Failed to update the field: {k} We'll skip it. Error: {str(e)}", color="red")
507
508
  pass
508
509
 
509
510
  return self
@@ -584,11 +585,11 @@ class Agent(BaseModel):
584
585
 
585
586
  except Exception as e:
586
587
  self._times_executed += 1
587
- Logger().log(level="error", message=f"The agent failed to execute the task. Error: {str(e)}", color="red")
588
+ Logger(**self._logger_config, filename=self.key).log(level="error", message=f"The agent failed to execute the task. Error: {str(e)}", color="red")
588
589
  raw_response = self.execute_task(task, context, task_tools)
589
590
 
590
591
  if self._times_executed > self.max_retry_limit:
591
- Logger().log(level="error", message=f"Max retry limit has exceeded.", color="red")
592
+ Logger(**self._logger_config, filename=self.key).log(level="error", message=f"Max retry limit has exceeded.", color="red")
592
593
  raise e
593
594
 
594
595
  if self.max_rpm and self._rpm_controller:
@@ -597,6 +598,15 @@ class Agent(BaseModel):
597
598
  return raw_response
598
599
 
599
600
 
601
+ @property
602
+ def key(self):
603
+ """
604
+ A key to identify an agent. Used in storage, logging, and other recodings.
605
+ """
606
+ sanitized_role = self.role.lower().replace(" ", "-").replace("/", "").replace("{", "").replace("}", "").replace("\n", "")
607
+ return f"{str(self.id)}-{sanitized_role}"
608
+
609
+
600
610
  def __repr__(self):
601
611
  return f"Agent(role={self.role}, goal={self.goal}"
602
612
 
@@ -9,6 +9,9 @@ from versionhq.agent_network.model import AgentNetwork, Member, Formation
9
9
  from versionhq.agent.inhouse_agents import vhq_formation_planner
10
10
  from versionhq._utils import Logger
11
11
 
12
+ import chromadb
13
+ chromadb.api.client.SharedSystemClient.clear_system_cache()
14
+
12
15
 
13
16
  def form_agent_network(
14
17
  task: str,
@@ -85,7 +88,7 @@ def form_agent_network(
85
88
  members = []
86
89
  leader = str(res.pydantic.leader_agent) if res.pydantic else str(res.json_dict["leader_agent"])
87
90
 
88
- created_agents = [Agent(role=item, goal=item) for item in res.pydantic.agent_roles]
91
+ created_agents = [Agent(role=str(item), goal=str(item)) for item in res.pydantic.agent_roles]
89
92
  created_tasks = []
90
93
 
91
94
  if res.pydantic:
@@ -9,6 +9,7 @@ class Knowledge(BaseModel):
9
9
  """
10
10
  Knowlede class for collection of sources and setup for the vector store to query relevant context.
11
11
  """
12
+
12
13
  collection_name: Optional[str] = None
13
14
  sources: List[BaseKnowledgeSource] = Field(default_factory=list)
14
15
  storage: KnowledgeStorage = Field(default_factory=KnowledgeStorage)
@@ -40,11 +40,11 @@ class Mem0Storage(Storage):
40
40
  self.memory = MemoryClient(api_key=mem0_api_key)
41
41
 
42
42
 
43
- def _sanitize_role(self, role: str) -> str:
44
- """
45
- Sanitizes agent roles to ensure valid directory names.
46
- """
47
- return role.replace("\n", "").replace(" ", "_").replace("/", "_")
43
+ # def _sanitize_role(self, role: str) -> str:
44
+ # """
45
+ # Sanitizes agent roles to ensure valid directory names.
46
+ # """
47
+ # return role.replace("\n", "").replace(" ", "_").replace("/", "_")
48
48
 
49
49
 
50
50
  def save(self, value: Dict[str, Any] | str, metadata: Dict[str, Any]) -> None:
@@ -104,6 +104,5 @@ class Mem0Storage(Storage):
104
104
 
105
105
  def _get_agent_name(self):
106
106
  agents = self.agents if self.agents else []
107
- agents = [self._sanitize_role(agent.role) for agent in agents]
108
- agents = "_".join(agents)
107
+ agents = "_".join([item.key for item in agents])
109
108
  return agents
@@ -52,15 +52,13 @@ class BaseRAGStorage(ABC):
52
52
 
53
53
  def _initialize_agents(self) -> str:
54
54
  if self.agents:
55
- return "_".join(
56
- [self._sanitize_role(agent.role) for agent in self.agents]
57
- )
55
+ return "_".join([agent.key for agent in self.agents])
58
56
  return ""
59
57
 
60
- @abstractmethod
61
- def _sanitize_role(self, role: str) -> str:
62
- """Sanitizes agent roles to ensure valid directory names."""
63
- pass
58
+ # @abstractmethod
59
+ # def _sanitize_role(self, role: str) -> str:
60
+ # """Sanitizes agent roles to ensure valid directory names."""
61
+ # pass
64
62
 
65
63
  @abstractmethod
66
64
  def save(self, value: Any, metadata: Dict[str, Any]) -> None:
@@ -108,7 +106,7 @@ class RAGStorage(BaseRAGStorage):
108
106
  def __init__(self, type, allow_reset=True, embedder_config=None, agents=list(), path=None):
109
107
  super().__init__(type, allow_reset, embedder_config, agents)
110
108
  agents = agents
111
- agents = [self._sanitize_role(agent.role) for agent in agents]
109
+ agents = [agent.key for agent in agents]
112
110
  agents = "_".join(agents)
113
111
 
114
112
  self.agents = agents
@@ -129,23 +127,23 @@ class RAGStorage(BaseRAGStorage):
129
127
  from chromadb.config import Settings
130
128
 
131
129
  self._set_embedder_config()
132
- chroma_client = chromadb.PersistentClient(
133
- path=self.path if self.path else self.storage_file_name,
134
- settings=Settings(allow_reset=self.allow_reset),
135
- )
136
- self.app = chroma_client
137
-
138
130
  try:
131
+ chroma_client = chromadb.PersistentClient(
132
+ path=self.path if self.path else self.storage_file_name,
133
+ settings=Settings(allow_reset=self.allow_reset),
134
+ )
135
+ self.app = chroma_client
139
136
  self.collection = self.app.get_collection(name=self.type, embedding_function=self.embedder_config)
140
137
  except Exception:
141
- self.collection = self.app.create_collection(name=self.type, embedding_function=self.embedder_config)
138
+ if self.app:
139
+ self.collection = self.app.create_collection(name=self.type, embedding_function=self.embedder_config)
142
140
 
143
141
 
144
- def _sanitize_role(self, role: str) -> str:
145
- """
146
- Sanitizes agent roles to ensure valid directory names.
147
- """
148
- return role.replace("\n", "").replace(" ", "_").replace("/", "_")
142
+ # def _sanitize_role(self, role: str) -> str:
143
+ # """
144
+ # Sanitizes agent roles to ensure valid directory names.
145
+ # """
146
+ # return role.replace("\n", "").replace(" ", "_").replace("/", "_")
149
147
 
150
148
 
151
149
  def _build_storage_file_name(self, type: str, file_name: str) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: versionhq
3
- Version: 1.2.1.18
3
+ Version: 1.2.1.20
4
4
  Summary: An agentic orchestration framework for building agent networks that handle task automation.
5
5
  Author-email: Kuriko Iwai <kuriko@versi0n.io>
6
6
  License: MIT License
@@ -1,19 +1,19 @@
1
- versionhq/__init__.py,sha256=I1z2OKVSflVHMiWtAsm5qE2-pmpxTtiMQhcytzInHas,2892
1
+ versionhq/__init__.py,sha256=swg84hsZ4rVrvtBLOAN8LcDfiZRR1jJ2sZR9-_iTedg,2892
2
2
  versionhq/_utils/__init__.py,sha256=dzoZr4cBlh-2QZuPzTdehPUCe9lP1dmRtauD7qTjUaA,158
3
3
  versionhq/_utils/i18n.py,sha256=TwA_PnYfDLA6VqlUDPuybdV9lgi3Frh_ASsb_X8jJo8,1483
4
- versionhq/_utils/logger.py,sha256=zgogTwAY-ujDLrdryAKhdtoaNe1nOFajmEN0V8aMR34,3155
4
+ versionhq/_utils/logger.py,sha256=iHxGjm3BvUo5dHKLU88_pc0Z45wzSHOjyJGQkb7OADk,3255
5
5
  versionhq/_utils/process_config.py,sha256=YTGY_erW335RfceQfzS18YAqq-AAb-iSvKSjN7noD2E,782
6
6
  versionhq/_utils/usage_metrics.py,sha256=NXF18dn5NNvGK7EsQ4AAghpR8ppYOjMx6ABenLLHnmM,1066
7
7
  versionhq/_utils/vars.py,sha256=bZ5Dx_bFKlt3hi4-NNGXqdk7B23If_WaTIju2fiTyPQ,57
8
8
  versionhq/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  versionhq/agent/inhouse_agents.py,sha256=vupO1viYqVb7sKohIE1zThu6JArhh5JLo5LBeSnh0kM,2534
10
- versionhq/agent/model.py,sha256=acAFIDmCbSVbMIf0Qlp9lzhdF0f_201havj3RnYj0xw,25661
10
+ versionhq/agent/model.py,sha256=2sFRDYk47yzgzHKaS0JGobJ-4q96UV4uz11BAsF_RXA,26535
11
11
  versionhq/agent/parser.py,sha256=riG0dkdQCxH7uJ0AbdVdg7WvL0BXhUgJht0VtQvxJBc,4082
12
12
  versionhq/agent/rpm_controller.py,sha256=grezIxyBci_lDlwAlgWFRyR5KOocXeOhYkgN02dNFNE,2360
13
13
  versionhq/agent/TEMPLATES/Backstory.py,sha256=IAhGnnt6VUMe3wO6IzeyZPDNu7XE7Uiu3VEXUreOcKs,532
14
14
  versionhq/agent/TEMPLATES/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  versionhq/agent_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- versionhq/agent_network/formation.py,sha256=QHLbv4XgbmMEQpdoHGrV6_CQOW3kIe7Jp32G0HgpA90,7418
16
+ versionhq/agent_network/formation.py,sha256=7iGw20Dj2sFLAho6yfrdmonAwFcxINBDGFr2RU-Qz3s,7505
17
17
  versionhq/agent_network/model.py,sha256=hjtYIopAN52nStcM6TlV0b6ulRMrmzKH7jIkzNmZHDE,19265
18
18
  versionhq/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  versionhq/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -26,7 +26,7 @@ versionhq/clients/workflow/model.py,sha256=fqmTx8Y6P6i-sK045ENO88GDbf4WYY4hUA26R
26
26
  versionhq/knowledge/__init__.py,sha256=qW7IgssTA4_bFFV9ziOcYRfGjlq1c8bkb-HnfWknpuQ,567
27
27
  versionhq/knowledge/_utils.py,sha256=YWRF8U533cfZes_gZqUvdj-K24MD2ri1R0gjc_aPYyc,402
28
28
  versionhq/knowledge/embedding.py,sha256=KfHc__1THxb5jrg1EMrF-v944RDuIr2hE0l-MtM3Bp0,6826
29
- versionhq/knowledge/model.py,sha256=w29mrJv1kiznCh4P4yJMUQxIuyRw1Sk0XYtBXzCxaG4,1786
29
+ versionhq/knowledge/model.py,sha256=ixH8n5kLtJEp1nPAFYA0piYm-n0nnFDtWFp0r9YEVAs,1787
30
30
  versionhq/knowledge/source.py,sha256=-hEUPtJUHHMx4rUKtiHl19J8xAMw-WVBw34zwa2jZ08,13630
31
31
  versionhq/knowledge/source_docling.py,sha256=mg7bgvKePHn2LlA_XzSFCbS0zOo9xfu_aNOf5cEo6c4,5421
32
32
  versionhq/knowledge/storage.py,sha256=7oxCg3W9mFjYH1YmuH9kFtTbNxquzYFjuUjd_TlsB9E,8170
@@ -39,8 +39,8 @@ versionhq/memory/model.py,sha256=MPO8dDP5eAuk9td6bMOq5j2huLzCADFJDrTujHhcWQY,815
39
39
  versionhq/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
40
  versionhq/storage/base.py,sha256=p-Jas0fXQan_qotnRD6seQxrT2lj-uw9-SmHQhdppcs,355
41
41
  versionhq/storage/ltm_sqlite_storage.py,sha256=wdUiuwHfJocdk0UGqyrdU4S5Nae1rgsoRNu3LWmGFcI,3951
42
- versionhq/storage/mem0_storage.py,sha256=Nl0GlCNftZGTVxX-9DP5n_pN4QRxeHAhAPakCc0arBg,3819
43
- versionhq/storage/rag_storage.py,sha256=ScWC0vH327vnGw8UGscAOoIfqrq3mhvXT3vEKzHZJts,7441
42
+ versionhq/storage/mem0_storage.py,sha256=ZY8MELBWaINRv9YuRW5MxH7dj2cII-L0i3xSD6o1-2M,3781
43
+ versionhq/storage/rag_storage.py,sha256=bS2eE874obarYl-4hT6ZWYWTRsqtfuGpKgKzERmM6Uo,7433
44
44
  versionhq/storage/task_output_storage.py,sha256=E1t_Fkt78dPYIOl3MP7LfQ8oGtjlzxBuSNq_8ZXKho8,4573
45
45
  versionhq/storage/utils.py,sha256=ByYXPoEIGJYLUqz-DWjbCAnneNrH1otiYbp12SCILpM,747
46
46
  versionhq/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -61,8 +61,8 @@ versionhq/tool/composio_tool_vars.py,sha256=FvBuEXsOQUYnN7RTFxT20kAkiEYkxWKkiVtg
61
61
  versionhq/tool/decorator.py,sha256=C4ZM7Xi2gwtEMaSeRo-geo_g_MAkY77WkSLkAuY0AyI,1205
62
62
  versionhq/tool/model.py,sha256=PO4zNWBZcJhYVur381YL1dy6zqurio2jWjtbxOxZMGI,12194
63
63
  versionhq/tool/tool_handler.py,sha256=2m41K8qo5bGCCbwMFferEjT-XZ-mE9F0mDUOBkgivOI,1416
64
- versionhq-1.2.1.18.dist-info/LICENSE,sha256=cRoGGdM73IiDs6nDWKqPlgSv7aR4n-qBXYnJlCMHCeE,1082
65
- versionhq-1.2.1.18.dist-info/METADATA,sha256=NvKh5tYpJbFp0SHQaukksKnHOCrzO2SBGJfO0rJlTZM,22033
66
- versionhq-1.2.1.18.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
67
- versionhq-1.2.1.18.dist-info/top_level.txt,sha256=DClQwxDWqIUGeRJkA8vBlgeNsYZs4_nJWMonzFt5Wj0,10
68
- versionhq-1.2.1.18.dist-info/RECORD,,
64
+ versionhq-1.2.1.20.dist-info/LICENSE,sha256=cRoGGdM73IiDs6nDWKqPlgSv7aR4n-qBXYnJlCMHCeE,1082
65
+ versionhq-1.2.1.20.dist-info/METADATA,sha256=KzJg8vQM1tOkvS9seXV_wCgcgN5l_bG0xw9KcvxWVI0,22033
66
+ versionhq-1.2.1.20.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
67
+ versionhq-1.2.1.20.dist-info/top_level.txt,sha256=DClQwxDWqIUGeRJkA8vBlgeNsYZs4_nJWMonzFt5Wj0,10
68
+ versionhq-1.2.1.20.dist-info/RECORD,,