wip: gemini doing gui_2.py catchup track
This commit is contained in:
@@ -15,5 +15,5 @@ This file tracks all major tracks for the project. Each track has its own detail
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- [ ] **Track: get gui_2 working with latest changes to the project.**
|
- [~] **Track: get gui_2 working with latest changes to the project.**
|
||||||
*Link: [./tracks/gui2_feature_parity_20260223/](./tracks/gui2_feature_parity_20260223/)*
|
*Link: [./tracks/gui2_feature_parity_20260223/](./tracks/gui2_feature_parity_20260223/)*
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ For features involving the GUI or complex internal state, unit tests are often i
|
|||||||
# The GUI is now running on port 8999
|
# The GUI is now running on port 8999
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
Note: pytest must be run with `uv`.
|
||||||
|
|
||||||
3. **Verify via ApiHookClient:** Use the `ApiHookClient` in `api_hook_client.py` to interact with the running application. It includes robust retry logic and health checks.
|
3. **Verify via ApiHookClient:** Use the `ApiHookClient` in `api_hook_client.py` to interact with the running application. It includes robust retry logic and health checks.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# config.toml
|
|
||||||
[ai]
|
[ai]
|
||||||
provider = "gemini"
|
provider = "gemini"
|
||||||
model = "gemini-1.5-pro-latest"
|
model = "gemini-2.0-flash"
|
||||||
temperature = 0.0
|
temperature = 0.0
|
||||||
max_tokens = 8192
|
max_tokens = 8192
|
||||||
history_trunc_limit = 8000
|
history_trunc_limit = 8000
|
||||||
|
|||||||
78
gui_2.py
78
gui_2.py
@@ -590,28 +590,7 @@ class App:
|
|||||||
|
|
||||||
# ---------------------------------------------------------------- gui
|
# ---------------------------------------------------------------- gui
|
||||||
|
|
||||||
def _gui_func(self):
|
def _show_menus(self):
|
||||||
self.perf_monitor.start_frame()
|
|
||||||
|
|
||||||
# Process GUI task queue
|
|
||||||
self._process_pending_gui_tasks()
|
|
||||||
|
|
||||||
# Sync pending comms
|
|
||||||
with self._pending_comms_lock:
|
|
||||||
for c in self._pending_comms:
|
|
||||||
self._comms_log.append(c)
|
|
||||||
self._pending_comms.clear()
|
|
||||||
|
|
||||||
with self._pending_history_adds_lock:
|
|
||||||
if self._pending_history_adds:
|
|
||||||
self._scroll_disc_to_bottom = True
|
|
||||||
for item in self._pending_history_adds:
|
|
||||||
if item["role"] not in self.disc_roles:
|
|
||||||
self.disc_roles.append(item["role"])
|
|
||||||
self.disc_entries.append(item)
|
|
||||||
self._pending_history_adds.clear()
|
|
||||||
|
|
||||||
if imgui.begin_main_menu_bar():
|
|
||||||
if imgui.begin_menu("Windows"):
|
if imgui.begin_menu("Windows"):
|
||||||
for w in self.show_windows.keys():
|
for w in self.show_windows.keys():
|
||||||
_, self.show_windows[w] = imgui.menu_item(w, "", self.show_windows[w])
|
_, self.show_windows[w] = imgui.menu_item(w, "", self.show_windows[w])
|
||||||
@@ -639,7 +618,57 @@ class App:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.ai_status = f"error: {e}"
|
self.ai_status = f"error: {e}"
|
||||||
imgui.end_menu()
|
imgui.end_menu()
|
||||||
imgui.end_main_menu_bar()
|
|
||||||
|
def _gui_func(self):
|
||||||
|
self.perf_monitor.start_frame()
|
||||||
|
|
||||||
|
# Process GUI task queue
|
||||||
|
self._process_pending_gui_tasks()
|
||||||
|
|
||||||
|
# Sync pending comms
|
||||||
|
with self._pending_comms_lock:
|
||||||
|
for c in self._pending_comms:
|
||||||
|
self._comms_log.append(c)
|
||||||
|
self._pending_comms.clear()
|
||||||
|
|
||||||
|
with self._pending_history_adds_lock:
|
||||||
|
if self._pending_history_adds:
|
||||||
|
self._scroll_disc_to_bottom = True
|
||||||
|
for item in self._pending_history_adds:
|
||||||
|
if item["role"] not in self.disc_roles:
|
||||||
|
self.disc_roles.append(item["role"])
|
||||||
|
self.disc_entries.append(item)
|
||||||
|
self._pending_history_adds.clear()
|
||||||
|
|
||||||
|
# if imgui.begin_main_menu_bar():
|
||||||
|
# if imgui.begin_menu("Windows"):
|
||||||
|
# for w in self.show_windows.keys():
|
||||||
|
# _, self.show_windows[w] = imgui.menu_item(w, "", self.show_windows[w])
|
||||||
|
# imgui.end_menu()
|
||||||
|
# if imgui.begin_menu("Project"):
|
||||||
|
# if imgui.menu_item("Save All", "", False)[0]:
|
||||||
|
# self._flush_to_project()
|
||||||
|
# self._save_active_project()
|
||||||
|
# self._flush_to_config()
|
||||||
|
# save_config(self.config)
|
||||||
|
# self.ai_status = "config saved"
|
||||||
|
# if imgui.menu_item("Reset Session", "", False)[0]:
|
||||||
|
# ai_client.reset_session()
|
||||||
|
# ai_client.clear_comms_log()
|
||||||
|
# self._tool_log.clear()
|
||||||
|
# self._comms_log.clear()
|
||||||
|
# self.ai_status = "session reset"
|
||||||
|
# self.ai_response = ""
|
||||||
|
# if imgui.menu_item("Generate MD Only", "", False)[0]:
|
||||||
|
# try:
|
||||||
|
# md, path, *_ = self._do_generate()
|
||||||
|
# self.last_md = md
|
||||||
|
# self.last_md_path = path
|
||||||
|
# self.ai_status = f"md written: {path.name}"
|
||||||
|
# except Exception as e:
|
||||||
|
# self.ai_status = f"error: {e}"
|
||||||
|
# imgui.end_menu()
|
||||||
|
# imgui.end_main_menu_bar()
|
||||||
|
|
||||||
# ---- Projects
|
# ---- Projects
|
||||||
if self.show_windows["Projects"]:
|
if self.show_windows["Projects"]:
|
||||||
@@ -1590,9 +1619,12 @@ class App:
|
|||||||
self.runner_params.app_window_params.window_geometry.size = (1680, 1200)
|
self.runner_params.app_window_params.window_geometry.size = (1680, 1200)
|
||||||
self.runner_params.imgui_window_params.enable_viewports = True
|
self.runner_params.imgui_window_params.enable_viewports = True
|
||||||
self.runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.provide_full_screen_dock_space
|
self.runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.provide_full_screen_dock_space
|
||||||
|
self.runner_params.imgui_window_params.show_menu_bar = True
|
||||||
self.runner_params.ini_folder_type = hello_imgui.IniFolderType.current_folder
|
self.runner_params.ini_folder_type = hello_imgui.IniFolderType.current_folder
|
||||||
self.runner_params.ini_filename = "manualslop_layout.ini"
|
self.runner_params.ini_filename = "manualslop_layout.ini"
|
||||||
|
|
||||||
self.runner_params.callbacks.show_gui = self._gui_func
|
self.runner_params.callbacks.show_gui = self._gui_func
|
||||||
|
self.runner_params.callbacks.show_menus = self._show_menus
|
||||||
self.runner_params.callbacks.load_additional_fonts = self._load_fonts
|
self.runner_params.callbacks.load_additional_fonts = self._load_fonts
|
||||||
self.runner_params.callbacks.post_init = self._post_init
|
self.runner_params.callbacks.post_init = self._post_init
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
# manual_slop.toml
|
|
||||||
# Main project file for Manual Slop.
|
|
||||||
# This file is managed by the application and can be edited manually.
|
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "manual_slop"
|
name = "manual_slop"
|
||||||
git_dir = "C:/projects/manual_slop"
|
git_dir = "C:/projects/manual_slop"
|
||||||
@@ -47,8 +43,6 @@ roles = [
|
|||||||
active = "test for gemini conductor"
|
active = "test for gemini conductor"
|
||||||
auto_add = true
|
auto_add = true
|
||||||
|
|
||||||
[discussion.discussions]
|
|
||||||
|
|
||||||
[discussion.discussions.main]
|
[discussion.discussions.main]
|
||||||
git_commit = "9265f94d9756b1a37a7b8e195725654032d84747"
|
git_commit = "9265f94d9756b1a37a7b8e195725654032d84747"
|
||||||
last_updated = "2026-02-21T18:23:13"
|
last_updated = "2026-02-21T18:23:13"
|
||||||
@@ -71,7 +65,7 @@ history = [
|
|||||||
|
|
||||||
[discussion.discussions."test for gemini conductor"]
|
[discussion.discussions."test for gemini conductor"]
|
||||||
git_commit = "ccdba69214aea169a4e707da7b425ae0c6139fca"
|
git_commit = "ccdba69214aea169a4e707da7b425ae0c6139fca"
|
||||||
last_updated = "2026-02-23T19:03:19"
|
last_updated = "2026-02-23T21:03:27"
|
||||||
history = [
|
history = [
|
||||||
"User:\nadded a file to yoru exposed files read it.",
|
"User:\nadded a file to yoru exposed files read it.",
|
||||||
"User:\nI have read the `MainContext.md` file. It contains extensive documentation about the \"Manual Slop\" project.\n\nWas `MainContext.md` the file you were referring to? If not, please specify the file's name or path.",
|
"User:\nI have read the `MainContext.md` file. It contains extensive documentation about the \"Manual Slop\" project.\n\nWas `MainContext.md` the file you were referring to? If not, please specify the file's name or path.",
|
||||||
|
|||||||
@@ -8,70 +8,81 @@ Size=400,400
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Projects]
|
[Window][Projects]
|
||||||
Pos=209,396
|
ViewportPos=43,95
|
||||||
Size=387,337
|
ViewportId=0x78C57832
|
||||||
|
Size=897,649
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000014,0
|
DockId=0x0000000D,0
|
||||||
|
|
||||||
[Window][Files]
|
[Window][Files]
|
||||||
Pos=0,0
|
ViewportPos=3125,170
|
||||||
Size=207,1200
|
ViewportId=0x26D64416
|
||||||
|
Size=593,581
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000011,0
|
DockId=0x00000009,0
|
||||||
|
|
||||||
[Window][Screenshots]
|
[Window][Screenshots]
|
||||||
Pos=209,0
|
ViewportPos=3125,170
|
||||||
Size=387,171
|
ViewportId=0x26D64416
|
||||||
Collapsed=0
|
Pos=0,583
|
||||||
DockId=0x00000015,0
|
Size=593,574
|
||||||
|
|
||||||
[Window][Discussion History]
|
|
||||||
Pos=598,128
|
|
||||||
Size=554,619
|
|
||||||
Collapsed=0
|
|
||||||
DockId=0x0000000E,0
|
|
||||||
|
|
||||||
[Window][Provider]
|
|
||||||
Pos=209,913
|
|
||||||
Size=387,287
|
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000A,0
|
DockId=0x0000000A,0
|
||||||
|
|
||||||
[Window][Message]
|
[Window][Discussion History]
|
||||||
Pos=598,749
|
Pos=0,17
|
||||||
Size=554,451
|
Size=1680,730
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000000C,0
|
DockId=0x0000000C,0
|
||||||
|
|
||||||
[Window][Response]
|
[Window][Provider]
|
||||||
Pos=209,735
|
ViewportPos=43,95
|
||||||
Size=387,176
|
ViewportId=0x78C57832
|
||||||
|
Pos=0,651
|
||||||
|
Size=897,468
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000010,0
|
DockId=0x0000000E,0
|
||||||
|
|
||||||
|
[Window][Message]
|
||||||
|
Pos=0,749
|
||||||
|
Size=1680,451
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000F,0
|
||||||
|
|
||||||
|
[Window][Response]
|
||||||
|
Pos=0,749
|
||||||
|
Size=1680,451
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000F,1
|
||||||
|
|
||||||
[Window][Tool Calls]
|
[Window][Tool Calls]
|
||||||
Pos=1154,733
|
ViewportPos=43,95
|
||||||
Size=526,144
|
ViewportId=0x78C57832
|
||||||
|
Pos=0,1121
|
||||||
|
Size=897,775
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000008,0
|
DockId=0x00000001,1
|
||||||
|
|
||||||
[Window][Comms History]
|
[Window][Comms History]
|
||||||
Pos=1154,879
|
ViewportPos=43,95
|
||||||
Size=526,321
|
ViewportId=0x78C57832
|
||||||
|
Pos=0,1121
|
||||||
|
Size=897,775
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000001,0
|
||||||
|
|
||||||
[Window][System Prompts]
|
[Window][System Prompts]
|
||||||
Pos=1154,0
|
Pos=0,749
|
||||||
Size=286,731
|
Size=1680,451
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000017,0
|
DockId=0x0000000F,2
|
||||||
|
|
||||||
[Window][Theme]
|
[Window][Theme]
|
||||||
Pos=209,173
|
ViewportPos=43,95
|
||||||
Size=387,221
|
ViewportId=0x78C57832
|
||||||
|
Size=897,649
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000016,0
|
DockId=0x0000000D,2
|
||||||
|
|
||||||
[Window][Text Viewer - Entry #7]
|
[Window][Text Viewer - Entry #7]
|
||||||
Pos=379,324
|
Pos=379,324
|
||||||
@@ -79,37 +90,24 @@ Size=900,700
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Diagnostics]
|
[Window][Diagnostics]
|
||||||
Pos=1442,0
|
ViewportPos=43,95
|
||||||
Size=238,731
|
ViewportId=0x78C57832
|
||||||
|
Size=897,649
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000018,0
|
DockId=0x0000000D,1
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=346,232 Size=1680,1200 Split=X
|
DockNode ID=0x00000007 Pos=43,95 Size=897,1896 Split=Y
|
||||||
DockNode ID=0x00000011 Parent=0xAFC85805 SizeRef=207,1200 Selected=0x0469CA7A
|
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=1029,1119 Split=Y
|
||||||
DockNode ID=0x00000012 Parent=0xAFC85805 SizeRef=1559,1200 Split=X
|
DockNode ID=0x0000000D Parent=0x00000002 SizeRef=1029,649 Selected=0xB4CBF21A
|
||||||
DockNode ID=0x00000003 Parent=0x00000012 SizeRef=943,1200 Split=X
|
DockNode ID=0x0000000E Parent=0x00000002 SizeRef=1029,468 Selected=0xA07B5F14
|
||||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=387,1200 Split=Y Selected=0x8CA2375C
|
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=1029,775 Selected=0x8B4EBFA6
|
||||||
DockNode ID=0x00000009 Parent=0x00000001 SizeRef=405,911 Split=Y Selected=0x8CA2375C
|
DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y
|
||||||
DockNode ID=0x0000000F Parent=0x00000009 SizeRef=405,733 Split=Y Selected=0x8CA2375C
|
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A
|
||||||
DockNode ID=0x00000013 Parent=0x0000000F SizeRef=405,394 Split=Y Selected=0x8CA2375C
|
DockNode ID=0x0000000A Parent=0x00000008 SizeRef=1029,145 Selected=0xDF822E02
|
||||||
DockNode ID=0x00000015 Parent=0x00000013 SizeRef=405,171 Selected=0xDF822E02
|
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=1052,572 Size=1680,1183 Split=Y
|
||||||
DockNode ID=0x00000016 Parent=0x00000013 SizeRef=405,221 Selected=0x8CA2375C
|
DockNode ID=0x0000000C Parent=0xAFC85805 SizeRef=1362,1041 CentralNode=1 Selected=0x5D11106F
|
||||||
DockNode ID=0x00000014 Parent=0x0000000F SizeRef=405,337 Selected=0xDA22FEDA
|
DockNode ID=0x0000000F Parent=0xAFC85805 SizeRef=1362,451 Selected=0xDD6419BC
|
||||||
DockNode ID=0x00000010 Parent=0x00000009 SizeRef=405,176 Selected=0x0D5A5273
|
|
||||||
DockNode ID=0x0000000A Parent=0x00000001 SizeRef=405,287 Selected=0xA07B5F14
|
|
||||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=554,1200 Split=Y
|
|
||||||
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1010,747 Split=Y
|
|
||||||
DockNode ID=0x0000000D Parent=0x0000000B SizeRef=1010,126 CentralNode=1
|
|
||||||
DockNode ID=0x0000000E Parent=0x0000000B SizeRef=1010,619 Selected=0x5D11106F
|
|
||||||
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=1010,451 Selected=0x66CFB56E
|
|
||||||
DockNode ID=0x00000004 Parent=0x00000012 SizeRef=526,1200 Split=Y Selected=0xDD6419BC
|
|
||||||
DockNode ID=0x00000005 Parent=0x00000004 SizeRef=261,877 Split=Y Selected=0xDD6419BC
|
|
||||||
DockNode ID=0x00000007 Parent=0x00000005 SizeRef=261,731 Split=X Selected=0xDD6419BC
|
|
||||||
DockNode ID=0x00000017 Parent=0x00000007 SizeRef=286,731 Selected=0xDD6419BC
|
|
||||||
DockNode ID=0x00000018 Parent=0x00000007 SizeRef=238,731 Selected=0xB4CBF21A
|
|
||||||
DockNode ID=0x00000008 Parent=0x00000005 SizeRef=261,144 Selected=0x1D56B311
|
|
||||||
DockNode ID=0x00000006 Parent=0x00000004 SizeRef=261,321 Selected=0x8B4EBFA6
|
|
||||||
|
|
||||||
;;;<<<Layout_655921752_Default>>>;;;
|
;;;<<<Layout_655921752_Default>>>;;;
|
||||||
;;;<<<HelloImGui_Misc>>>;;;
|
;;;<<<HelloImGui_Misc>>>;;;
|
||||||
@@ -119,6 +117,6 @@ Name=Default
|
|||||||
Show=false
|
Show=false
|
||||||
ShowFps=true
|
ShowFps=true
|
||||||
[Theme]
|
[Theme]
|
||||||
Name=DarculaDarker
|
Name=SoDark_AccentRed
|
||||||
;;;<<<SplitIds>>>;;;
|
;;;<<<SplitIds>>>;;;
|
||||||
{"gImGuiSplitIDs":{"MainDockSpace":2949142533}}
|
{"gImGuiSplitIDs":{"MainDockSpace":2949142533}}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ git_dir = "C:\\projects\\manual_slop"
|
|||||||
system_prompt = ""
|
system_prompt = ""
|
||||||
main_context = ""
|
main_context = ""
|
||||||
word_wrap = true
|
word_wrap = true
|
||||||
|
summary_only = false
|
||||||
|
|
||||||
[output]
|
[output]
|
||||||
output_dir = "./md_gen"
|
output_dir = "./md_gen"
|
||||||
@@ -37,5 +38,7 @@ auto_add = true
|
|||||||
|
|
||||||
[discussion.discussions.main]
|
[discussion.discussions.main]
|
||||||
git_commit = ""
|
git_commit = ""
|
||||||
last_updated = "2026-02-23T19:53:17"
|
last_updated = "2026-02-23T20:56:57"
|
||||||
history = []
|
history = [
|
||||||
|
"@2026-02-23T20:12:12\nSystem:\n[PERFORMANCE ALERT] CPU usage high: 121.9%. Please consider optimizing recent changes or reducing load.",
|
||||||
|
]
|
||||||
|
|||||||
78
tests/test_gui2_mcp.py
Normal file
78
tests/test_gui2_mcp.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import pytest
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
from gui_2 import App
|
||||||
|
import ai_client
|
||||||
|
from events import EventEmitter
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def app_instance():
|
||||||
|
if not hasattr(ai_client, 'events') or ai_client.events is None:
|
||||||
|
ai_client.events = EventEmitter()
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch('gui_2.load_config', return_value={'ai': {}, 'projects': {}}),
|
||||||
|
patch('gui_2.save_config'),
|
||||||
|
patch('gui_2.project_manager'),
|
||||||
|
patch('gui_2.session_logger'),
|
||||||
|
patch('gui_2.immapp.run'),
|
||||||
|
patch.object(App, '_load_active_project'),
|
||||||
|
patch.object(App, '_fetch_models'),
|
||||||
|
patch.object(App, '_load_fonts'),
|
||||||
|
patch.object(App, '_post_init')
|
||||||
|
):
|
||||||
|
yield App()
|
||||||
|
|
||||||
|
def test_mcp_tool_call_is_dispatched(app_instance):
|
||||||
|
"""
|
||||||
|
This test verifies that when the AI returns a tool call for an MCP function,
|
||||||
|
the ai_client correctly dispatches it to mcp_client.
|
||||||
|
This will fail until mcp_client is properly integrated.
|
||||||
|
"""
|
||||||
|
# 1. Define the mock tool call from the AI
|
||||||
|
mock_fc = MagicMock()
|
||||||
|
mock_fc.name = "read_file"
|
||||||
|
mock_fc.args = {"file_path": "test.txt"}
|
||||||
|
|
||||||
|
# 2. Construct the mock AI response (Gemini format)
|
||||||
|
mock_response_with_tool = MagicMock()
|
||||||
|
mock_part = MagicMock()
|
||||||
|
mock_part.function_call = mock_fc
|
||||||
|
mock_candidate = MagicMock()
|
||||||
|
mock_candidate.content.parts = [mock_part]
|
||||||
|
mock_candidate.finish_reason.name = "TOOL_CALLING"
|
||||||
|
mock_response_with_tool.candidates = [mock_candidate]
|
||||||
|
|
||||||
|
mock_usage_metadata = MagicMock()
|
||||||
|
mock_usage_metadata.prompt_token_count = 100
|
||||||
|
mock_usage_metadata.candidates_token_count = 10
|
||||||
|
mock_usage_metadata.cached_content_token_count = 0
|
||||||
|
mock_response_with_tool.usage_metadata = mock_usage_metadata
|
||||||
|
|
||||||
|
# 3. Create a mock for the final AI response after the tool call
|
||||||
|
mock_response_final = MagicMock()
|
||||||
|
mock_response_final.text = "Final answer"
|
||||||
|
mock_response_final.candidates = []
|
||||||
|
mock_response_final.usage_metadata = mock_usage_metadata
|
||||||
|
|
||||||
|
# 4. Patch the necessary components
|
||||||
|
with patch("ai_client._ensure_gemini_client"), \
|
||||||
|
patch("ai_client._gemini_client"), \
|
||||||
|
patch("ai_client._gemini_chat") as mock_chat, \
|
||||||
|
patch('mcp_client.dispatch', return_value="file content") as mock_dispatch:
|
||||||
|
|
||||||
|
mock_chat.send_message.side_effect = [mock_response_with_tool, mock_response_final]
|
||||||
|
ai_client._gemini_chat = mock_chat
|
||||||
|
|
||||||
|
ai_client.set_provider("gemini", "mock-model")
|
||||||
|
|
||||||
|
# 5. Call the send function
|
||||||
|
ai_client.send(
|
||||||
|
md_content="some context",
|
||||||
|
user_message="read the file",
|
||||||
|
base_dir=".",
|
||||||
|
file_items=[],
|
||||||
|
discussion_history=""
|
||||||
|
)
|
||||||
|
|
||||||
|
# 6. Assert that the MCP dispatch function was called
|
||||||
|
mock_dispatch.assert_called_once_with("read_file", {"file_path": "test.txt"})
|
||||||
Reference in New Issue
Block a user