feat read files
This commit is contained in:
1 parent
78152d9974
commit
f129aef5a5
3 files changed
+175
-11
No files matched your search
@@ -439,7 +439,7 @@ class ModelLoaderThread(QThread):
|
||||
|
||||
|
||||
class AskThread(QThread):
|
||||
tool_call = pyqtSignal(str)
|
||||
tool_call = pyqtSignal(str, str)
|
||||
usage = pyqtSignal(dict)
|
||||
token = pyqtSignal(str)
|
||||
thinking_token = pyqtSignal(str)
|
||||
@@ -479,6 +479,11 @@ class ChatWindow(QMainWindow):
|
||||
self._sessions[0] if self._sessions else chatbot.new_session()
|
||||
)
|
||||
self._history: list[tuple[str, str]] = list(self._current_session.history)
|
||||
# The loaded model has a single KV cache. Each chat keeps its own
|
||||
# snapshot of that cache so switching chats restores that chat's
|
||||
# context instead of continuing whichever chat ran last.
|
||||
self._context_states: dict[str, object] = {}
|
||||
self._context_owner: str | None = None
|
||||
self._pending_question = ""
|
||||
self._ask_thread: AskThread | None = None
|
||||
# Position in chat_view's document where the in-progress streamed
|
||||
@@ -718,6 +723,7 @@ class ChatWindow(QMainWindow):
|
||||
return # already on an empty, unsaved chat
|
||||
self._current_session = chatbot.new_session()
|
||||
self._history = []
|
||||
self._activate_session_context(self._current_session)
|
||||
self.chat_view.clear()
|
||||
self._append_system("Dev assist chatbot ready. Ask a development question.")
|
||||
self.session_list.clearSelection()
|
||||
@@ -734,6 +740,7 @@ class ChatWindow(QMainWindow):
|
||||
return
|
||||
self._current_session = session
|
||||
self._history = list(session.history)
|
||||
self._activate_session_context(session)
|
||||
self._render_session_history(session)
|
||||
self.statusBar().showMessage("Ready.")
|
||||
|
||||
@@ -759,6 +766,9 @@ class ChatWindow(QMainWindow):
|
||||
if reply != QMessageBox.StandardButton.Yes:
|
||||
return
|
||||
chatbot.delete_session(session_id)
|
||||
self._context_states.pop(session_id, None)
|
||||
if self._context_owner == session_id:
|
||||
self._context_owner = None
|
||||
self._sessions = [s for s in self._sessions if s.id != session_id]
|
||||
if self._current_session.id == session_id:
|
||||
if self._sessions:
|
||||
@@ -766,6 +776,7 @@ class ChatWindow(QMainWindow):
|
||||
else:
|
||||
self._current_session = chatbot.new_session()
|
||||
self._history = list(self._current_session.history)
|
||||
self._activate_session_context(self._current_session)
|
||||
self.chat_view.clear()
|
||||
if self._current_session.history:
|
||||
self._render_session_history(self._current_session)
|
||||
@@ -776,7 +787,7 @@ class ChatWindow(QMainWindow):
|
||||
def _on_model_loaded(self, llm) -> None:
|
||||
self._llm = llm
|
||||
self._n_ctx = llm.n_ctx()
|
||||
self.context_status_label.setText(f"Context: 0 / {self._n_ctx}")
|
||||
self._activate_session_context(self._current_session)
|
||||
self.statusBar().showMessage("Ready.")
|
||||
self._append_system("Dev assist chatbot ready. Ask a development question.")
|
||||
self._set_input_enabled(True)
|
||||
@@ -799,6 +810,7 @@ class ChatWindow(QMainWindow):
|
||||
self._answer_started = False
|
||||
self._stream_thinking_id = None
|
||||
|
||||
self._activate_session_context(self._current_session)
|
||||
messages = chatbot.build_messages(self._history, question)
|
||||
self._pending_question = question
|
||||
|
||||
@@ -936,16 +948,47 @@ class ChatWindow(QMainWindow):
|
||||
return
|
||||
self._render_thinking(block_id, expanded=not block["expanded"])
|
||||
|
||||
def _on_tool_call(self, query: str) -> None:
|
||||
def _on_tool_call(self, tool_name: str, target: str) -> None:
|
||||
self._collapse_open_thinking()
|
||||
self._discard_stream_card()
|
||||
self.statusBar().showMessage(f"Searching: {query}")
|
||||
self._append_system(f"Searching the web for: {query}")
|
||||
if tool_name == "read_file":
|
||||
self.statusBar().showMessage(f"Reading file: {target}")
|
||||
self._append_system(f"Reading file: {target}")
|
||||
else:
|
||||
self.statusBar().showMessage(f"Searching: {target}")
|
||||
self._append_system(f"Searching the web for: {target}")
|
||||
|
||||
def _show_context_usage(self, total: int | None) -> None:
|
||||
if total is None or not self._n_ctx:
|
||||
shown = "--" if total is None else total
|
||||
limit = self._n_ctx or "--"
|
||||
self.context_status_label.setText(f"Context: {shown} / {limit}")
|
||||
return
|
||||
pct = 100 * total / self._n_ctx
|
||||
self.context_status_label.setText(f"Context: {total} / {self._n_ctx} ({pct:.0f}%)")
|
||||
|
||||
def _activate_session_context(self, session: "chatbot.ChatSession") -> None:
|
||||
"""Make the loaded model's KV cache match this chat.
|
||||
|
||||
Leaving a chat stores its cache; entering one restores it, or clears
|
||||
the cache when that chat has no snapshot yet (first visit this run).
|
||||
"""
|
||||
self._show_context_usage(session.context_tokens)
|
||||
if self._llm is None or self._context_owner == session.id:
|
||||
return
|
||||
if self._context_owner is not None:
|
||||
self._context_states[self._context_owner] = self._llm.save_state()
|
||||
state = self._context_states.get(session.id)
|
||||
if state is None:
|
||||
self._llm.reset()
|
||||
else:
|
||||
self._llm.load_state(state)
|
||||
self._context_owner = session.id
|
||||
|
||||
def _on_usage(self, usage: dict) -> None:
|
||||
total = usage["total_tokens"]
|
||||
pct = 100 * total / self._n_ctx if self._n_ctx else 0
|
||||
self.context_status_label.setText(f"Context: {total} / {self._n_ctx} ({pct:.0f}%)")
|
||||
self._current_session.context_tokens = total
|
||||
self._show_context_usage(total)
|
||||
|
||||
def _on_answer(self, answer: str) -> None:
|
||||
# Normally already collapsed by the first answer token (_on_token),
|
||||
|
||||
Reference in new issue
Block a user