cube-chat 0.1.0__tar.gz

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,8 @@
1
+ Metadata-Version: 2.3
2
+ Name: cube-chat
3
+ Version: 0.1.0
4
+ Summary: Concrete chat session implementations for cube-standard
5
+ Requires-Dist: cube-standard
6
+ Requires-Dist: pytest>=8.0.0 ; extra == 'dev'
7
+ Requires-Python: >=3.12
8
+ Provides-Extra: dev
@@ -0,0 +1,38 @@
1
+ [project]
2
+ name = "cube-chat"
3
+ version = "0.1.0"
4
+ description = "Concrete chat session implementations for cube-standard"
5
+ requires-python = ">=3.12"
6
+ dependencies = [
7
+ "cube-standard",
8
+ ]
9
+
10
+ [project.optional-dependencies]
11
+ dev = [
12
+ "pytest>=8.0.0",
13
+ ]
14
+
15
+ [build-system]
16
+ requires = ["uv_build>=0.6.0,<0.7.0"]
17
+ build-backend = "uv_build"
18
+
19
+ [tool.uv.build-backend]
20
+ module-name = "cube_chat"
21
+
22
+ [tool.ruff]
23
+ fix = true
24
+ line-length = 120
25
+ indent-width = 4
26
+
27
+ [tool.ruff.format]
28
+ quote-style = "double"
29
+ indent-style = "space"
30
+ skip-magic-trailing-comma = false
31
+ line-ending = "auto"
32
+
33
+ [tool.ruff.lint]
34
+ extend-select = ["I"]
35
+
36
+ [tool.pytest.ini_options]
37
+ testpaths = ["tests"]
38
+ addopts = "-rs"
@@ -0,0 +1,5 @@
1
+ """cube-chat: concrete chat session implementations for cube-standard."""
2
+
3
+ from cube_chat.chat_session import BasicChatConfig, BasicChatSession, SessionStoppedError
4
+
5
+ __all__ = ["BasicChatConfig", "BasicChatSession", "SessionStoppedError"]
@@ -0,0 +1,99 @@
1
+ """In-memory chat session implementation using a queue."""
2
+
3
+ import queue
4
+ import time
5
+
6
+ from cube.resources.chat_session import ChatConfig, ChatMessage, ChatRole, ChatSession
7
+
8
+ _STORED_ROLES = {"user", "assistant", "infeasible"}
9
+ _VALID_ROLES = {"user", "assistant", "info", "infeasible"}
10
+ _STOP_SENTINEL = None
11
+
12
+
13
+ class SessionStoppedError(Exception):
14
+ """Raised by wait_for_user_message() when stop() has been called."""
15
+
16
+
17
+ class BasicChatConfig(ChatConfig):
18
+ """Configuration for an in-memory BasicChatSession.
19
+
20
+ No configuration fields are needed for the in-memory implementation.
21
+ """
22
+
23
+ def make(self) -> "BasicChatSession":
24
+ """Create and return a new BasicChatSession."""
25
+ return BasicChatSession()
26
+
27
+
28
+ class BasicChatSession(ChatSession):
29
+ """In-memory chat session backed by a queue.
30
+
31
+ Messages posted with add_message() for roles "user", "assistant", and
32
+ "infeasible" are stored in history. The "info" role is silently dropped
33
+ (not stored). send_message() appends an "assistant" message and unblocks
34
+ any caller waiting in wait_for_user_message().
35
+ """
36
+
37
+ def __init__(self) -> None:
38
+ self._messages: list[ChatMessage] = []
39
+ self._queue: queue.SimpleQueue[str | None] = queue.SimpleQueue()
40
+
41
+ @property
42
+ def messages(self) -> list[ChatMessage]:
43
+ """Return a copy of the full message history."""
44
+ return self._messages[:]
45
+
46
+ def add_message(self, role: ChatRole, msg: str) -> None:
47
+ """Post a message to the chat from the task side.
48
+
49
+ Parameters
50
+ ----------
51
+ role : ChatRole
52
+ Role of the message sender. "info" messages are not stored.
53
+ msg : str
54
+ Message content.
55
+
56
+ Raises
57
+ ------
58
+ ValueError
59
+ If role is not a valid ChatRole.
60
+ """
61
+ if role not in _VALID_ROLES:
62
+ raise ValueError(f"Invalid role '{role}'. Must be one of: {sorted(_VALID_ROLES)}")
63
+ if role in _STORED_ROLES:
64
+ self._messages.append(ChatMessage(role=role, timestamp=time.time(), message=msg))
65
+
66
+ def wait_for_user_message(self) -> str:
67
+ """Block until the agent sends a message and return it.
68
+
69
+ Returns
70
+ -------
71
+ str
72
+ The agent's message text.
73
+
74
+ Raises
75
+ ------
76
+ SessionStoppedError
77
+ If stop() was called while blocked or before this call.
78
+ """
79
+ msg = self._queue.get()
80
+ if msg is _STOP_SENTINEL:
81
+ raise SessionStoppedError("Session has been stopped")
82
+ return msg
83
+
84
+ def send_message(self, text: str) -> None:
85
+ """Send a message from the agent side, unblocking wait_for_user_message().
86
+
87
+ Appends an "assistant" message to history and puts the text into the queue.
88
+
89
+ Parameters
90
+ ----------
91
+ text : str
92
+ Message content to send.
93
+ """
94
+ self._messages.append(ChatMessage(role="assistant", timestamp=time.time(), message=text))
95
+ self._queue.put(text)
96
+
97
+ def stop(self) -> None:
98
+ """Unblock any thread waiting in wait_for_user_message() and mark the session stopped."""
99
+ self._queue.put(_STOP_SENTINEL)