Spaces:
Runtime error
Runtime error
tech-envision
commited on
Commit
·
114361d
1
Parent(s):
09df150
document session registry
Browse files- README.md +5 -0
- src/chat.py +42 -5
README.md
CHANGED
@@ -12,6 +12,11 @@ conversations can be resumed with context. One example tool is included:
|
|
12 |
responding while they execute. The VM is created when a chat session starts
|
13 |
and reused for all subsequent tool calls.
|
14 |
|
|
|
|
|
|
|
|
|
|
|
15 |
The application injects a robust system prompt on each request. The prompt
|
16 |
guides the model to plan tool usage, execute commands sequentially and
|
17 |
verify results before replying. It is **not** stored in the chat history but is
|
|
|
12 |
responding while they execute. The VM is created when a chat session starts
|
13 |
and reused for all subsequent tool calls.
|
14 |
|
15 |
+
Sessions share state through an in-memory registry so that only one generation
|
16 |
+
can run at a time. Messages sent while a response is being produced are
|
17 |
+
ignored unless the assistant is waiting for a tool result—in that case the
|
18 |
+
pending response is cancelled and replaced with the new request.
|
19 |
+
|
20 |
The application injects a robust system prompt on each request. The prompt
|
21 |
guides the model to plan tool usage, execute commands sequentially and
|
22 |
verify results before replying. It is **not** stored in the chat history but is
|
src/chat.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
from __future__ import annotations
|
2 |
|
3 |
from typing import List, AsyncIterator
|
|
|
4 |
import json
|
5 |
import asyncio
|
6 |
import shutil
|
@@ -29,6 +30,27 @@ from .schema import Msg
|
|
29 |
from .tools import execute_terminal, execute_terminal_async, set_vm
|
30 |
from .vm import VMRegistry
|
31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
_LOG = get_logger(__name__)
|
33 |
|
34 |
|
@@ -49,9 +71,26 @@ class ChatSession:
|
|
49 |
)
|
50 |
self._vm = None
|
51 |
self._messages: List[Msg] = self._load_history()
|
52 |
-
self.
|
53 |
-
self.
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
async def __aenter__(self) -> "ChatSession":
|
57 |
self._vm = VMRegistry.acquire(self._user.username)
|
@@ -365,5 +404,3 @@ class ChatSession:
|
|
365 |
continue
|
366 |
if part.message.content:
|
367 |
yield part.message.content
|
368 |
-
|
369 |
-
|
|
|
1 |
from __future__ import annotations
|
2 |
|
3 |
from typing import List, AsyncIterator
|
4 |
+
from dataclasses import dataclass, field
|
5 |
import json
|
6 |
import asyncio
|
7 |
import shutil
|
|
|
30 |
from .tools import execute_terminal, execute_terminal_async, set_vm
|
31 |
from .vm import VMRegistry
|
32 |
|
33 |
+
|
34 |
+
@dataclass
|
35 |
+
class _SessionData:
|
36 |
+
"""Shared state for each conversation session."""
|
37 |
+
|
38 |
+
lock: asyncio.Lock = field(default_factory=asyncio.Lock)
|
39 |
+
state: str = "idle"
|
40 |
+
tool_task: asyncio.Task | None = None
|
41 |
+
|
42 |
+
|
43 |
+
_SESSION_DATA: dict[int, _SessionData] = {}
|
44 |
+
|
45 |
+
|
46 |
+
def _get_session_data(conv_id: int) -> _SessionData:
|
47 |
+
data = _SESSION_DATA.get(conv_id)
|
48 |
+
if data is None:
|
49 |
+
data = _SessionData()
|
50 |
+
_SESSION_DATA[conv_id] = data
|
51 |
+
return data
|
52 |
+
|
53 |
+
|
54 |
_LOG = get_logger(__name__)
|
55 |
|
56 |
|
|
|
71 |
)
|
72 |
self._vm = None
|
73 |
self._messages: List[Msg] = self._load_history()
|
74 |
+
self._data = _get_session_data(self._conversation.id)
|
75 |
+
self._lock = self._data.lock
|
76 |
+
|
77 |
+
# Shared state properties -------------------------------------------------
|
78 |
+
|
79 |
+
@property
|
80 |
+
def _state(self) -> str:
|
81 |
+
return self._data.state
|
82 |
+
|
83 |
+
@_state.setter
|
84 |
+
def _state(self, value: str) -> None:
|
85 |
+
self._data.state = value
|
86 |
+
|
87 |
+
@property
|
88 |
+
def _tool_task(self) -> asyncio.Task | None:
|
89 |
+
return self._data.tool_task
|
90 |
+
|
91 |
+
@_tool_task.setter
|
92 |
+
def _tool_task(self, task: asyncio.Task | None) -> None:
|
93 |
+
self._data.tool_task = task
|
94 |
|
95 |
async def __aenter__(self) -> "ChatSession":
|
96 |
self._vm = VMRegistry.acquire(self._user.username)
|
|
|
404 |
continue
|
405 |
if part.message.content:
|
406 |
yield part.message.content
|
|
|
|