h-ai-brain 0.0.6__py3-none-any.whl → 0.0.8__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.
@@ -1,17 +1,22 @@
1
- import datetime
2
-
3
1
  from h_message_bus import NatsPublisherAdapter
4
- from h_message_bus.domain.twitter_get_user_request_message import TwitterGetUserRequestMessage
5
- from h_message_bus.domain.twitter_get_user_response_message import TwitterGetUserResponseMessage
6
- from h_message_bus.domain.vector_save_request_message import VectorSaveRequestMessage
7
-
2
+ from h_message_bus.domain.request_messages.twitter_get_user_request_message import TwitterGetUserRequestMessage
3
+ from h_message_bus.domain.request_messages.twitter_get_user_response_message import TwitterGetUserResponseMessage
4
+ from h_message_bus.domain.request_messages.vector_read_metadata_request_message import VectorReadMetaDataRequestMessage
5
+ from h_message_bus.domain.request_messages.vector_read_metadata_response_message import \
6
+ VectorReadMetaDataResponseMessage
7
+ from h_message_bus.domain.request_messages.vector_save_request_message import VectorSaveRequestMessage
8
+
9
+ from .priority_queue_service import PriorityQueueService
8
10
  from ..application.web_docs_service import WebDocsService
11
+ from ..infrastructure.priorityqueue.in_memory_priority_queue_repository import InMemoryPriorityQueueRepository
9
12
 
10
13
 
11
14
  class HaiService:
12
15
  def __init__(self, nats_publisher_adapter: NatsPublisherAdapter):
13
16
  self.nats_publisher_adapter = nats_publisher_adapter
14
17
  self.web_docs_service = WebDocsService()
18
+ queue = InMemoryPriorityQueueRepository()
19
+ self.queue_service = PriorityQueueService(queue)
15
20
 
16
21
  async def detect_and_store_documentation(self, twitter_screen_name: str):
17
22
  req_message = TwitterGetUserRequestMessage.create_message(twitter_screen_name)
@@ -31,8 +36,7 @@ class HaiService:
31
36
  document_id = f"{doc.title}_{chapter.heading}_{i}"
32
37
 
33
38
  req_metadata = {
34
- "source": doc.url,
35
- "updated": datetime.datetime.utcnow().isoformat()
39
+ "source": doc.url
36
40
  }
37
41
  i = i + 1
38
42
 
@@ -45,4 +49,10 @@ class HaiService:
45
49
  await self.nats_publisher_adapter.publish(request)
46
50
 
47
51
  else:
48
- print(f"No documentation found for {twitter_user.screen_name}")
52
+ print(f"No documentation found for {twitter_user.screen_name}")
53
+
54
+ async def load_current_knowledge_base_metadata(self):
55
+ message = VectorReadMetaDataRequestMessage.create_message()
56
+ response = await self.nats_publisher_adapter.request(message)
57
+ metadata_result = VectorReadMetaDataResponseMessage.from_hai_message(response)
58
+ print(metadata_result)
@@ -0,0 +1,34 @@
1
+
2
+ from typing import Any, List, Optional
3
+
4
+ from ..domain.priorityqueue.priority_queue_repository import PriorityQueueRepository
5
+ from ..domain.priorityqueue.queue_item import QueueItem
6
+
7
+
8
+ class PriorityQueueService:
9
+ """Application service to manage priority queue operations"""
10
+
11
+ def __init__(self, repository: PriorityQueueRepository):
12
+ self.repository = repository
13
+
14
+ def add_item(self, queue_name: str, content: Any, priority: int, metadata: Optional[dict] = None) -> QueueItem:
15
+ """Add an item to the specified queue"""
16
+ item = QueueItem.create(content, priority, metadata)
17
+ self.repository.add_item(queue_name, item)
18
+ return item
19
+
20
+ def get_next_item(self, queue_name: str) -> Optional[QueueItem]:
21
+ """Get and remove the highest priority item from the queue"""
22
+ return self.repository.get_highest_priority_item(queue_name)
23
+
24
+ def get_items(self, queue_name: str, limit: int = 10) -> List[QueueItem]:
25
+ """Get multiple items from the queue in priority order without removing them"""
26
+ return self.repository.get_items(queue_name, limit)
27
+
28
+ def get_queue_length(self, queue_name: str) -> int:
29
+ """Get the number of items in the queue"""
30
+ return self.repository.queue_length(queue_name)
31
+
32
+ def get_available_queues(self) -> List[str]:
33
+ """Get a list of all available queue names"""
34
+ return self.repository.get_queue_names()
File without changes
@@ -0,0 +1,34 @@
1
+
2
+ from abc import ABC, abstractmethod
3
+ from typing import List, Optional
4
+
5
+ from .queue_item import QueueItem
6
+
7
+
8
+ class PriorityQueueRepository(ABC):
9
+ """Repository interface for priority queue operations"""
10
+
11
+ @abstractmethod
12
+ def add_item(self, queue_name: str, item: QueueItem) -> None:
13
+ """Add an item to the specified queue"""
14
+ pass
15
+
16
+ @abstractmethod
17
+ def get_highest_priority_item(self, queue_name: str, block: bool = False, timeout: Optional[float] = None) -> Optional[QueueItem]:
18
+ """Get and remove the highest priority item from the queue"""
19
+ pass
20
+
21
+ # @abstractmethod
22
+ # def get_items(self, queue_name: str, limit: int = 10) -> List[QueueItem]:
23
+ # """Get multiple items from the queue in priority order without removing them"""
24
+ # pass
25
+
26
+ @abstractmethod
27
+ def queue_length(self, queue_name: str) -> int:
28
+ """Get the number of items in the queue"""
29
+ pass
30
+
31
+ @abstractmethod
32
+ def get_queue_names(self) -> List[str]:
33
+ """Get a list of all available queue names"""
34
+ pass
@@ -0,0 +1,43 @@
1
+
2
+ import uuid
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import Optional
6
+
7
+ from h_message_bus import HaiMessage
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class QueueItem:
12
+ """Value object representing an item in the priority queue"""
13
+ id: str
14
+ content: HaiMessage
15
+ priority: int
16
+ created_at: datetime
17
+ metadata: Optional[dict] = None
18
+
19
+ @classmethod
20
+ def create(cls, content: HaiMessage, priority: int, metadata: Optional[dict] = None) -> "QueueItem":
21
+ """Factory method to create a new QueueItem"""
22
+ return cls(
23
+ id=str(uuid.uuid4()),
24
+ content=content,
25
+ priority=priority,
26
+ created_at=datetime.utcnow(),
27
+ metadata=metadata
28
+ )
29
+
30
+ def __lt__(self, other):
31
+ """Comparison method for priority queue ordering
32
+ - Primary sort by priority: Higher number = higher priority
33
+ - Secondary sort by timestamp: Earlier timestamp = higher priority (FIFO)
34
+ """
35
+ if not isinstance(other, QueueItem):
36
+ return NotImplemented
37
+
38
+ # First, compare by priority (higher priority value comes first)
39
+ if self.priority != other.priority:
40
+ return self.priority > other.priority
41
+
42
+ # If priorities are equal, compare by timestamp (older timestamp comes first)
43
+ return self.created_at < other.created_at
File without changes
@@ -0,0 +1,98 @@
1
+ import queue
2
+ import threading
3
+ from queue import PriorityQueue
4
+ from typing import Dict, List, Optional
5
+
6
+ from ...domain.priorityqueue.priority_queue_repository import PriorityQueueRepository
7
+ from ...domain.priorityqueue.queue_item import QueueItem
8
+
9
+
10
+ class InMemoryPriorityQueueRepository(PriorityQueueRepository):
11
+ """In-memory implementation of the PriorityQueueRepository using Python's PriorityQueue"""
12
+
13
+ def __init__(self):
14
+ # Dictionary mapping queue names to their PriorityQueue instances
15
+ self.queues: Dict[str, PriorityQueue] = {}
16
+ # Locks to ensure thread safety
17
+ self.locks: Dict[str, threading.Lock] = {}
18
+
19
+ def _get_or_create_queue(self, queue_name: str, maxsize: int = 10000) -> PriorityQueue:
20
+ """Get or create a queue with the given name"""
21
+ if queue_name not in self.queues:
22
+ self.queues[queue_name] = PriorityQueue(maxsize=maxsize)
23
+ self.locks[queue_name] = threading.Lock()
24
+ return self.queues[queue_name]
25
+
26
+ def _get_lock(self, queue_name: str) -> threading.Lock:
27
+ """Get the lock for the specified queue"""
28
+ if queue_name not in self.locks:
29
+ self.locks[queue_name] = threading.Lock()
30
+ return self.locks[queue_name]
31
+
32
+ def add_item(self, queue_name: str, item: QueueItem) -> None:
33
+ """Add an item to the specified queue"""
34
+ q = self._get_or_create_queue(queue_name)
35
+ with self._get_lock(queue_name):
36
+ # The queue automatically orders by priority
37
+ q.put(item)
38
+
39
+ def get_highest_priority_item(self, queue_name: str, block: bool = False, timeout: Optional[float] = None) -> Optional[QueueItem]:
40
+ """Get and remove the highest priority item from the queue"""
41
+ if queue_name not in self.queues:
42
+ return None
43
+
44
+ q = self.queues[queue_name]
45
+ try:
46
+ # We need to acquire the lock to check initially, but then we need to release it
47
+ # so that other threads can add items while we're blocking
48
+ with self._get_lock(queue_name):
49
+ # If not blocking and queue is empty, return immediately
50
+ if not block and q.empty():
51
+ return None
52
+
53
+ # Note: queue.get() with block=True will internally manage locking
54
+ # We don't hold our custom lock during the blocking wait
55
+ return q.get(block=block, timeout=timeout)
56
+ except queue.Empty:
57
+ # This will be raised if timeout occurs with no items
58
+ return None
59
+
60
+
61
+ def get_items(self, queue_name: str, limit: int = 10) -> List[QueueItem]:
62
+ """Get multiple items from the queue in priority order without removing them"""
63
+ if queue_name not in self.queues:
64
+ return []
65
+
66
+ q = self.queues[queue_name]
67
+ result = []
68
+
69
+ with self._get_lock(queue_name):
70
+ # Create a temporary list to hold items that we'll put back
71
+ temp_items = []
72
+
73
+ # Get up to 'limit' items
74
+ count = 0
75
+ while not q.empty() and count < limit:
76
+ item = q.get()
77
+ temp_items.append(item)
78
+ result.append(item)
79
+ count += 1
80
+
81
+ # Put all the items back in the same order
82
+ for item in temp_items:
83
+ q.put(item)
84
+
85
+ return result
86
+
87
+ def queue_length(self, queue_name: str) -> int:
88
+ """Get the number of items in the queue"""
89
+ if queue_name not in self.queues:
90
+ return 0
91
+
92
+ q = self.queues[queue_name]
93
+ with self._get_lock(queue_name):
94
+ return q.qsize()
95
+
96
+ def get_queue_names(self) -> List[str]:
97
+ """Get a list of all available queue names"""
98
+ return list(self.queues.keys())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: h_ai_brain
3
- Version: 0.0.6
3
+ Version: 0.0.8
4
4
  Summary: AI Research agent API
5
5
  Author-email: shoebill <shoebill.hai@gmail.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,10 +1,14 @@
1
1
  h_ai/__init__.py,sha256=bmHMDoui52Q73UvXdHslQ3w_LubmhRuKRlrjOYyCP8c,153
2
2
  h_ai/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- h_ai/application/hai_service.py,sha256=DpSx1_QYS_3N5OwY5U4My0WwH-e4tvRHNeJxSduGoZM,2200
3
+ h_ai/application/hai_service.py,sha256=ZSbDLP8oCBliLpbhpKOf7Xv6cWDsLCSeDeurn207FsA,3005
4
+ h_ai/application/priority_queue_service.py,sha256=qi1PZMLYxy3HzG6cu-2hLijUYGcYGYMpzAp4S0vl0I0,1462
4
5
  h_ai/application/web_docs_service.py,sha256=YiPBfPyjlloDq6CIOP0u7F1jNBK-elYRU8xl4qJ1oVc,1652
5
6
  h_ai/application/system_prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
7
  h_ai/application/system_prompts/roles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
8
  h_ai/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ h_ai/domain/priorityqueue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ h_ai/domain/priorityqueue/priority_queue_repository.py,sha256=_px-WFlsj439EKV1qN-z85rQDeybhs2p-xGEXRpOtHE,1104
11
+ h_ai/domain/priorityqueue/queue_item.py,sha256=aP2Sd3ig9dgKnAsKE_rr3uRjJ_ClWIrvz0Y3nC8XbmE,1417
8
12
  h_ai/domain/reasoning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
13
  h_ai/domain/reasoning/llm_chat_repository.py,sha256=rY2izDyaDnoyyrCRS1qc9erHB98vARj4Mp-SnPwNhyY,211
10
14
  h_ai/domain/reasoning/llm_generate_respository.py,sha256=DPiV6ldCE8YhDdVb5rj98MBudKalDQHV3CZ2ADTm_f8,178
@@ -42,9 +46,11 @@ h_ai/infrastructure/llm/ollama/models/ollama_chat_message.py,sha256=ZIz4PQ3869vI
42
46
  h_ai/infrastructure/llm/ollama/models/ollama_chat_session.py,sha256=GZ_ddpbWa8iy6NZq50vokUFVZBiX0WNa81z9-r9RzTY,392
43
47
  h_ai/infrastructure/playwright/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
48
  h_ai/infrastructure/playwright/playwright_web_content_fetcher.py,sha256=FVwcK6hv_6aE4fYlJapLHyxNHsztQkKaulklHabyrEc,2684
45
- h_ai_brain-0.0.6.dist-info/licenses/LICENSE,sha256=SbvpEU5JIU3yzMMkyzrI0dGqHDoJR_lMKGdl6GZHsy4,11558
46
- h_ai_brain-0.0.6.dist-info/licenses/NOTICE.txt,sha256=vxeIKUiGqAePLvDW4AVm3Xh-3BcsvMtCMn1tbsr9zsE,668
47
- h_ai_brain-0.0.6.dist-info/METADATA,sha256=taZvGg8xXlBSu13t5DKFWXBPybB8k6Zi0Izjk3qpLv8,735
48
- h_ai_brain-0.0.6.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
49
- h_ai_brain-0.0.6.dist-info/top_level.txt,sha256=3MChDBWvDJV4cEHuZhzeODxQ4ewtw-arOuyaDOc6sIo,5
50
- h_ai_brain-0.0.6.dist-info/RECORD,,
49
+ h_ai/infrastructure/priorityqueue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ h_ai/infrastructure/priorityqueue/in_memory_priority_queue_repository.py,sha256=zxnrbzoLfiKQMB28dI1bPe0qUtvIDG8OEFcTQL_UeFg,3886
51
+ h_ai_brain-0.0.8.dist-info/licenses/LICENSE,sha256=SbvpEU5JIU3yzMMkyzrI0dGqHDoJR_lMKGdl6GZHsy4,11558
52
+ h_ai_brain-0.0.8.dist-info/licenses/NOTICE.txt,sha256=vxeIKUiGqAePLvDW4AVm3Xh-3BcsvMtCMn1tbsr9zsE,668
53
+ h_ai_brain-0.0.8.dist-info/METADATA,sha256=tO3CbkRDXPuG4cTEIPA8sOtgyXqEMk7ew-KBTA0NGUA,735
54
+ h_ai_brain-0.0.8.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
55
+ h_ai_brain-0.0.8.dist-info/top_level.txt,sha256=3MChDBWvDJV4cEHuZhzeODxQ4ewtw-arOuyaDOc6sIo,5
56
+ h_ai_brain-0.0.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (79.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5