From e670fc1c3ec0c1fada07933b52b2c201c8f61af7 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 6 Jun 2026 00:40:07 -0400 Subject: [PATCH] more org --- _repro.py | 29 ------------------ src/diff_viewer.py | 62 ++++++++++++++++++--------------------- src/events.py | 53 +++++++++++++++------------------ src/fuzzy_anchor.py | 4 +-- src/gemini_cli_adapter.py | 12 ++++---- src/hot_reloader.py | 2 +- 6 files changed, 60 insertions(+), 102 deletions(-) delete mode 100644 _repro.py diff --git a/_repro.py b/_repro.py deleted file mode 100644 index da041ad8..00000000 --- a/_repro.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Minimal reproducer for the auto_switch_sim GUI crash.""" -import sys -import time -import os -sys.path.insert(0, 'C:/projects/manual_slop') -sys.path.insert(0, 'C:/projects/manual_slop/src') - -from src.api_hook_client import ApiHookClient -client = ApiHookClient() -if not client.wait_for_server(timeout=15): - print('FAIL: server not up') - sys.exit(1) -print('OK: server up') - -print('Step 1: click btn_reset') -client.click('btn_reset') -time.sleep(1.0) -print('Step 1 done, status=', client.get_value('ai_status')) - -print('Step 2: set_value current_provider gemini_cli') -client.set_value('current_provider', 'gemini_cli') -time.sleep(1.0) -print('Step 2 done') - -print('Step 3: set_value gcli_path') -mock_path = os.path.abspath('tests/mock_concurrent_mma.py') -client.set_value('gcli_path', '"' + sys.executable + '" "' + mock_path + '"') -time.sleep(1.0) -print('Step 3 done') diff --git a/src/diff_viewer.py b/src/diff_viewer.py index d4c8f7c5..cf5ee8d5 100644 --- a/src/diff_viewer.py +++ b/src/diff_viewer.py @@ -1,3 +1,4 @@ +import difflib import shutil import os @@ -8,8 +9,8 @@ from typing import List, Dict, Optional, Tuple @dataclass class DiffHunk: - header: str - lines: List[str] + header: str + lines: List[str] old_start: int old_count: int new_start: int @@ -19,18 +20,16 @@ class DiffHunk: class DiffFile: old_path: str new_path: str - hunks: List[DiffHunk] + hunks: List[DiffHunk] def parse_hunk_header(line: str) -> Optional[tuple[int, int, int, int]]: """ - [C: tests/test_diff_viewer.py:test_parse_hunk_header] + [C: tests/test_diff_viewer.py:test_parse_hunk_header] """ - if not line.startswith("@@"): - return None + if not line.startswith("@@"): return None parts = line.split() - if len(parts) < 2: - return None + if len(parts) < 2: return None old_part = parts[1][1:] new_part = parts[2][1:] @@ -52,7 +51,7 @@ def parse_diff(diff_text: str) -> List[DiffFile]: if not diff_text or not diff_text.strip(): return [] - files: List[DiffFile] = [] + files: List[DiffFile] = [] current_file: Optional[DiffFile] = None current_hunk: Optional[DiffHunk] = None @@ -83,21 +82,21 @@ def parse_diff(diff_text: str) -> List[DiffFile]: if hunk_info: old_start, old_count, new_start, new_count = hunk_info current_hunk = DiffHunk( - header=line, - lines=[], - old_start=old_start, - old_count=old_count, - new_start=new_start, - new_count=new_count + header = line, + lines = [], + old_start = old_start, + old_count = old_count, + new_start = new_start, + new_count = new_count ) else: current_hunk = DiffHunk( - header=line, - lines=[], - old_start=0, - old_count=0, - new_start=0, - new_count=0 + header = line, + lines = [], + old_start = 0, + old_count = 0, + new_start = 0, + new_count = 0 ) elif current_hunk is not None: @@ -115,22 +114,17 @@ def parse_diff(diff_text: str) -> List[DiffFile]: def get_line_color(line: str) -> Optional[str]: """ - [C: tests/test_diff_viewer.py:test_get_line_color] + [C: tests/test_diff_viewer.py:test_get_line_color] """ - if line.startswith("+"): - return "green" - elif line.startswith("-"): - return "red" - elif line.startswith("@@"): - return "cyan" + if line.startswith("+"): return "green" + elif line.startswith("-"): return "red" + elif line.startswith("@@"): return "cyan" return None def apply_patch_to_file(patch_text: str, base_dir: str = ".") -> Tuple[bool, str]: """ - [C: src/gui_2.py:App._apply_pending_patch, tests/test_diff_viewer.py:test_apply_patch_simple, tests/test_diff_viewer.py:test_apply_patch_with_context] + [C: src/gui_2.py:App._apply_pending_patch, tests/test_diff_viewer.py:test_apply_patch_simple, tests/test_diff_viewer.py:test_apply_patch_with_context] """ - import difflib - diff_files = parse_diff(patch_text) if not diff_files: return False, "No valid diff found" @@ -147,7 +141,7 @@ def apply_patch_to_file(patch_text: str, base_dir: str = ".") -> Tuple[bool, str original_lines = f.read().splitlines(keepends=True) new_lines = original_lines.copy() - offset = 0 + offset = 0 for hunk in df.hunks: hunk_old_start = hunk.old_start - 1 @@ -158,13 +152,13 @@ def apply_patch_to_file(patch_text: str, base_dir: str = ".") -> Tuple[bool, str hunk_new_content: List[str] = [] for line in hunk.lines: - if line.startswith("+") and not line.startswith("+++"): + if line.startswith("+") and not line.startswith("+++"): hunk_new_content.append(line[1:] + "\n") elif line.startswith(" ") or (line and not line.startswith(("-", "+", "@@"))): hunk_new_content.append(line + "\n") new_lines = new_lines[:replace_start] + hunk_new_content + new_lines[replace_start + replace_count:] - offset += len(hunk_new_content) - replace_count + offset += len(hunk_new_content) - replace_count with open(file_path, "w", encoding="utf-8", newline="") as f: f.writelines(new_lines) diff --git a/src/events.py b/src/events.py index cbd64a91..7082ed11 100644 --- a/src/events.py +++ b/src/events.py @@ -5,18 +5,18 @@ This module provides three complementary patterns for thread-safe communication between the GUI main thread and background workers: 1. EventEmitter: Pub/sub pattern for synchronous event broadcast - - Used for: API lifecycle events (request_start, response_received, tool_execution) - - Thread-safe: Callbacks execute on emitter's thread - - Example: ai_client.py emits 'request_start' and 'response_received' events + - Used for: API lifecycle events (request_start, response_received, tool_execution) + - Thread-safe: Callbacks execute on emitter's thread + - Example: ai_client.py emits 'request_start' and 'response_received' events 2. AsyncEventQueue: Producer-consumer pattern via queue.Queue - - Used for: Decoupled task submission where consumer polls at its own pace - - Thread-safe: Built on Python's thread-safe queue.Queue - - Example: Background workers submit tasks, main thread drains queue + - Used for: Decoupled task submission where consumer polls at its own pace + - Thread-safe: Built on Python's thread-safe queue.Queue + - Example: Background workers submit tasks, main thread drains queue 3. UserRequestEvent: Structured payload for AI request data - - Used for: Bundling prompt, context, files, and base_dir into single object - - Immutable data transfer object for cross-thread handoff + - Used for: Bundling prompt, context, files, and base_dir into single object + - Immutable data transfer object for cross-thread handoff Integration Points: - ai_client.py: EventEmitter for API lifecycle events @@ -138,9 +138,8 @@ class AsyncEventQueue: def join(self) -> None: """ - - Blocks until all items in the queue have been gotten and processed. - [C: simulation/live_walkthrough.py:main, simulation/ping_pong.py:module, simulation/sim_base.py:module, src/file_cache.py:ASTParser.get_code_outline, src/fuzzy_anchor.py:FuzzyAnchor.create_slice, src/fuzzy_anchor.py:FuzzyAnchor.resolve_slice, src/gemini_cli_adapter.py:GeminiCliAdapter.count_tokens, src/gemini_cli_adapter.py:GeminiCliAdapter.send, src/gui_2.py:App._render_ast_inspector_modal, src/gui_2.py:App._render_beads_tab, src/gui_2.py:App._render_discussion_entry, src/gui_2.py:App._render_mma_ticket_editor, src/log_pruner.py:LogPruner.prune, src/log_registry.py:LogRegistry.update_auto_whitelist_status, src/markdown_helper.py:MarkdownRenderer._render_code_block, src/mcp_client.py:StdioMCPServer.call_tool, src/mcp_client.py:_resolve_and_check, src/mcp_client.py:derive_code_path, src/mcp_client.py:dispatch, src/mcp_client.py:fetch_url, src/mcp_client.py:get_file_slice, src/mcp_client.py:get_tree, src/mcp_client.py:list_directory, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_class_summary, src/mcp_client.py:py_get_definition, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:py_get_imports, src/mcp_client.py:py_get_signature, src/mcp_client.py:py_get_symbol_info, src/mcp_client.py:py_get_var_declaration, src/mcp_client.py:search_files, src/mcp_client.py:set_file_slice, src/mcp_client.py:web_search, src/models.py:parse_history_entries, src/multi_agent_conductor.py:ConductorEngine.kill_worker, src/multi_agent_conductor.py:WorkerPool.join_all, src/orchestrator_pm.py:generate_tracks, src/orchestrator_pm.py:get_track_history_summary, src/outline_tool.py:CodeOutliner.outline, src/performance_monitor.py:PerformanceMonitor.stop, src/project_manager.py:str_to_entry, src/rag_engine.py:RAGEngine._init_vector_store, src/rag_engine.py:RAGEngine.index_file, src/session_logger.py:open_session, src/shell_runner.py:_build_subprocess_env, src/shell_runner.py:run_powershell, src/summarize.py:_summarise_generic, src/summarize.py:_summarise_markdown, src/summarize.py:_summarise_python, src/summarize.py:_summarise_toml, src/summarize.py:build_summary_markdown, src/synthesis_formatter.py:format_takes_diff, src/tool_bias.py:ToolBiasEngine.generate_tooling_strategy, tests/conftest.py:live_gui, tests/conftest.py:module, tests/mock_gemini_cli.py:main, tests/smoke_status_hook.py:module, tests/test_agent_capabilities.py:module, tests/test_agent_tools_wiring.py:module, tests/test_ai_client_concurrency.py:test_ai_client_tier_isolation, tests/test_api_hook_client.py:module, tests/test_api_hook_extensions.py:module, tests/test_arch_boundary_phase1.py:module, tests/test_arch_boundary_phase2.py:module, tests/test_arch_boundary_phase3.py:module, tests/test_auto_switch_sim.py:module, tests/test_cli_tool_bridge.py:module, tests/test_cli_tool_bridge_mapping.py:module, tests/test_context_composition_phase3.py:test_compute_file_stats, tests/test_context_pruner.py:test_performance_large_file, tests/test_context_pruner.py:test_token_reduction_logging, tests/test_deepseek_infra.py:module, tests/test_extended_sims.py:module, tests/test_external_editor_gui.py:module, tests/test_gemini_metrics.py:module, tests/test_gui2_parity.py:module, tests/test_gui2_performance.py:module, tests/test_gui_diagnostics.py:module, tests/test_gui_performance_requirements.py:module, tests/test_gui_stress_performance.py:module, tests/test_gui_updates.py:module, tests/test_headless_service.py:module, tests/test_history_management.py:module, tests/test_hooks.py:module, tests/test_layout_reorganization.py:module, tests/test_live_workflow.py:module, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_handles_relative_paths_starting_with_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_empty_sessions_regardless_of_age, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_sessions_without_metadata_regardless_of_age, tests/test_log_registry.py:TestLogRegistry.setUp, tests/test_mcp_perf_tool.py:module, tests/test_mcp_ts_integration.py:module, tests/test_mma_approval_indicators.py:_collect_text_colored_args, tests/test_mma_concurrent_tracks_sim.py:module, tests/test_mma_concurrent_tracks_stress_sim.py:module, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders, tests/test_mma_step_mode_sim.py:module, tests/test_patch_modal_gui.py:module, tests/test_performance_monitor.py:module, tests/test_phase6_simulation.py:module, tests/test_rag_integration.py:mock_project, tests/test_rag_integration.py:test_rag_integration, tests/test_rag_phase4_final_verify.py:module, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:module, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_rag_visual_sim.py:module, tests/test_selectable_ui.py:module, tests/test_sim_ai_settings.py:module, tests/test_sim_base.py:module, tests/test_sim_context.py:module, tests/test_sim_execution.py:module, tests/test_sim_tools.py:module, tests/test_skeleton_injection.py:test_update_inject_preview_truncation, tests/test_spawn_interception_v2.py:test_confirm_spawn_pushed_to_queue, tests/test_system_prompt_exposure.py:module, tests/test_token_usage.py:module, tests/test_tool_management_layout.py:module, tests/test_ts_c_tools.py:module, tests/test_ts_cpp_tools.py:module, tests/test_ui_cache_controls_sim.py:module, tests/test_user_agent.py:module, tests/test_visual_orchestration.py:module, tests/test_visual_sim_mma_v2.py:module, tests/test_workflow_sim.py:module, tests/test_workspace_profiles_sim.py:module] + Blocks until all items in the queue have been gotten and processed. + [C: simulation/live_walkthrough.py:main, simulation/ping_pong.py:module, simulation/sim_base.py:module, src/file_cache.py:ASTParser.get_code_outline, src/fuzzy_anchor.py:FuzzyAnchor.create_slice, src/fuzzy_anchor.py:FuzzyAnchor.resolve_slice, src/gemini_cli_adapter.py:GeminiCliAdapter.count_tokens, src/gemini_cli_adapter.py:GeminiCliAdapter.send, src/gui_2.py:App._render_ast_inspector_modal, src/gui_2.py:App._render_beads_tab, src/gui_2.py:App._render_discussion_entry, src/gui_2.py:App._render_mma_ticket_editor, src/log_pruner.py:LogPruner.prune, src/log_registry.py:LogRegistry.update_auto_whitelist_status, src/markdown_helper.py:MarkdownRenderer._render_code_block, src/mcp_client.py:StdioMCPServer.call_tool, src/mcp_client.py:_resolve_and_check, src/mcp_client.py:derive_code_path, src/mcp_client.py:dispatch, src/mcp_client.py:fetch_url, src/mcp_client.py:get_file_slice, src/mcp_client.py:get_tree, src/mcp_client.py:list_directory, src/mcp_client.py:py_find_usages, src/mcp_client.py:py_get_class_summary, src/mcp_client.py:py_get_definition, src/mcp_client.py:py_get_hierarchy, src/mcp_client.py:py_get_imports, src/mcp_client.py:py_get_signature, src/mcp_client.py:py_get_symbol_info, src/mcp_client.py:py_get_var_declaration, src/mcp_client.py:search_files, src/mcp_client.py:set_file_slice, src/mcp_client.py:web_search, src/models.py:parse_history_entries, src/multi_agent_conductor.py:ConductorEngine.kill_worker, src/multi_agent_conductor.py:WorkerPool.join_all, src/orchestrator_pm.py:generate_tracks, src/orchestrator_pm.py:get_track_history_summary, src/outline_tool.py:CodeOutliner.outline, src/performance_monitor.py:PerformanceMonitor.stop, src/project_manager.py:str_to_entry, src/rag_engine.py:RAGEngine._init_vector_store, src/rag_engine.py:RAGEngine.index_file, src/session_logger.py:open_session, src/shell_runner.py:_build_subprocess_env, src/shell_runner.py:run_powershell, src/summarize.py:_summarise_generic, src/summarize.py:_summarise_markdown, src/summarize.py:_summarise_python, src/summarize.py:_summarise_toml, src/summarize.py:build_summary_markdown, src/synthesis_formatter.py:format_takes_diff, src/tool_bias.py:ToolBiasEngine.generate_tooling_strategy, tests/conftest.py:live_gui, tests/conftest.py:module, tests/mock_gemini_cli.py:main, tests/smoke_status_hook.py:module, tests/test_agent_capabilities.py:module, tests/test_agent_tools_wiring.py:module, tests/test_ai_client_concurrency.py:test_ai_client_tier_isolation, tests/test_api_hook_client.py:module, tests/test_api_hook_extensions.py:module, tests/test_arch_boundary_phase1.py:module, tests/test_arch_boundary_phase2.py:module, tests/test_arch_boundary_phase3.py:module, tests/test_auto_switch_sim.py:module, tests/test_cli_tool_bridge.py:module, tests/test_cli_tool_bridge_mapping.py:module, tests/test_context_composition_phase3.py:test_compute_file_stats, tests/test_context_pruner.py:test_performance_large_file, tests/test_context_pruner.py:test_token_reduction_logging, tests/test_deepseek_infra.py:module, tests/test_extended_sims.py:module, tests/test_external_editor_gui.py:module, tests/test_gemini_metrics.py:module, tests/test_gui2_parity.py:module, tests/test_gui2_performance.py:module, tests/test_gui_diagnostics.py:module, tests/test_gui_performance_requirements.py:module, tests/test_gui_stress_performance.py:module, tests/test_gui_updates.py:module, tests/test_headless_service.py:module, tests/test_history_management.py:module, tests/test_hooks.py:module, tests/test_layout_reorganization.py:module, tests/test_live_workflow.py:module, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_handles_relative_paths_starting_with_logs, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_empty_sessions_regardless_of_age, tests/test_log_pruning_heuristic.py:TestLogPruningHeuristic.test_prune_removes_sessions_without_metadata_regardless_of_age, tests/test_log_registry.py:TestLogRegistry.setUp, tests/test_mcp_perf_tool.py:module, tests/test_mcp_ts_integration.py:module, tests/test_mma_approval_indicators.py:_collect_text_colored_args, tests/test_mma_concurrent_tracks_sim.py:module, tests/test_mma_concurrent_tracks_stress_sim.py:module, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders, tests/test_mma_step_mode_sim.py:module, tests/test_patch_modal_gui.py:module, tests/test_performance_monitor.py:module, tests/test_phase6_simulation.py:module, tests/test_rag_integration.py:mock_project, tests/test_rag_integration.py:test_rag_integration, tests/test_rag_phase4_final_verify.py:module, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:module, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_rag_visual_sim.py:module, tests/test_selectable_ui.py:module, tests/test_sim_ai_settings.py:module, tests/test_sim_base.py:module, tests/test_sim_context.py:module, tests/test_sim_execution.py:module, tests/test_sim_tools.py:module, tests/test_skeleton_injection.py:test_update_inject_preview_truncation, tests/test_spawn_interception_v2.py:test_confirm_spawn_pushed_to_queue, tests/test_system_prompt_exposure.py:module, tests/test_token_usage.py:module, tests/test_tool_management_layout.py:module, tests/test_ts_c_tools.py:module, tests/test_ts_cpp_tools.py:module, tests/test_ui_cache_controls_sim.py:module, tests/test_user_agent.py:module, tests/test_visual_orchestration.py:module, tests/test_visual_sim_mma_v2.py:module, tests/test_workflow_sim.py:module, tests/test_workspace_profiles_sim.py:module] """ self._queue.join() @@ -154,35 +153,31 @@ class UserRequestEvent: def __init__(self, prompt: str, stable_md: str, file_items: List[Any], disc_text: str, base_dir: str) -> None: """ - [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] + [C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__] """ - self.prompt = prompt - self.stable_md = stable_md + self.prompt = prompt + self.stable_md = stable_md self.file_items = file_items - self.disc_text = disc_text - self.base_dir = base_dir + self.disc_text = disc_text + self.base_dir = base_dir def to_dict(self) -> Dict[str, Any]: """ [C: src/gui_2.py:App._take_snapshot, src/gui_2.py:App.save_context_preset, src/models.py:ContextPreset.to_dict, src/models.py:ExternalEditorConfig.to_dict, src/models.py:MCPConfiguration.to_dict, src/models.py:RAGConfig.to_dict, src/models.py:ToolPreset.to_dict, src/models.py:Track.to_dict, src/models.py:TrackState.to_dict, src/personas.py:PersonaManager.save_persona, src/presets.py:PresetManager.save_preset, src/project_manager.py:save_project, src/project_manager.py:save_track_state, src/tool_presets.py:ToolPresetManager.save_bias_profile, src/tool_presets.py:ToolPresetManager.save_preset, src/workspace_manager.py:WorkspaceManager.save_profile, tests/test_bias_models.py:test_bias_profile_model, tests/test_bias_models.py:test_tool_model, tests/test_bias_models.py:test_tool_preset_extension, tests/test_context_presets_models.py:test_context_preset_serialization, tests/test_context_presets_models.py:test_file_view_preset_serialization, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_round_trip_annotations, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_serialization_with_annotations, tests/test_event_serialization.py:test_user_request_event_serialization, tests/test_external_editor.py:TestExternalEditorConfig.test_to_dict, tests/test_external_editor.py:TestTextEditorConfig.test_to_dict, tests/test_file_item_model.py:test_file_item_to_dict, tests/test_gui_events_v2.py:test_user_request_event_payload, tests/test_history_manager.py:TestHistoryManager.test_snapshot_roundtrip, tests/test_mcp_config.py:test_mcp_configuration_to_from_dict, tests/test_mcp_config.py:test_mcp_server_config_to_from_dict, tests/test_per_ticket_model.py:test_model_override_serialization, tests/test_persona_id.py:test_ticket_persona_id_serialization, tests/test_persona_models.py:test_persona_defaults, tests/test_persona_models.py:test_persona_serialization, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations, tests/test_thinking_gui.py:test_thinking_segment_model_compatibility, tests/test_ticket_queue.py:test_ticket_to_dict_priority, tests/test_tiered_aggregation.py:test_persona_aggregation_strategy, tests/test_track_state_schema.py:test_track_state_to_dict, tests/test_track_state_schema.py:test_track_state_to_dict_with_none, tests/test_ui_summary_only_removal.py:test_file_item_serialization_with_flags] """ def _make_serializable(obj: Any) -> Any: - if isinstance(obj, dict): - return {k: _make_serializable(v) for k, v in obj.items()} - if isinstance(obj, list): - return [_make_serializable(x) for x in obj] - if isinstance(obj, Path): - return str(obj) - if hasattr(obj, 'to_dict'): - return obj.to_dict() + if isinstance(obj, dict): return {k: _make_serializable(v) for k, v in obj.items()} + if isinstance(obj, list): return [_make_serializable(x) for x in obj] + if isinstance(obj, Path): return str(obj) + if hasattr(obj, 'to_dict'): return obj.to_dict() if not isinstance(obj, (str, int, float, bool, type(None))): return str(obj) return obj return { - "prompt": self.prompt, - "stable_md": self.stable_md, + "prompt": self.prompt, + "stable_md": self.stable_md, "file_items": _make_serializable(self.file_items), - "disc_text": self.disc_text, - "base_dir": str(self.base_dir) - } \ No newline at end of file + "disc_text": self.disc_text, + "base_dir": str(self.base_dir) + } diff --git a/src/fuzzy_anchor.py b/src/fuzzy_anchor.py index 81af9ac0..f4fe2183 100644 --- a/src/fuzzy_anchor.py +++ b/src/fuzzy_anchor.py @@ -20,14 +20,14 @@ class FuzzyAnchor: def create_slice(cls, text: str, start_line: int, end_line: int) -> dict: """ start_line and end_line are 1-based. - [C: src/gui_2.py:App._populate_auto_slices, src/gui_2.py:App._render_text_viewer_window, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_create_slice_basic, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_anchor_mismatch_returns_none, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_exact_match, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_line_deleted_before_returns_none, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_line_inserted_before, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_multiple_lines_changed, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations] + [C: src/gui_2.py:App._populate_auto_slices, src/gui_2.py:App._render_text_viewer_window, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_create_slice_basic, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_anchor_mismatch_returns_none, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_exact_match, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_line_deleted_before_returns_none, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_line_inserted_before, tests/test_fuzzy_anchor.py:TestFuzzyAnchor.test_resolve_slice_multiple_lines_changed, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations] """ lines = text.splitlines() s_idx = max(0, start_line - 1) e_idx = min(len(lines), end_line) slice_lines = lines[s_idx:e_idx] slice_text = "\n".join(slice_lines) - + return { "start_line": start_line, "end_line": end_line, diff --git a/src/gemini_cli_adapter.py b/src/gemini_cli_adapter.py index b9bd13ea..a7136da1 100644 --- a/src/gemini_cli_adapter.py +++ b/src/gemini_cli_adapter.py @@ -189,18 +189,16 @@ class GeminiCliAdapter: self.last_latency = current_latency return { - "text": accumulated_text, + "text": accumulated_text, "tool_calls": tool_calls, - "stderr": stderr_final + "stderr": stderr_final } def count_tokens(self, contents: list[str]) -> int: """ - - - Provides a character-based token estimation for the Gemini CLI. - Uses 4 chars/token as a conservative average. - [C: tests/test_gemini_cli_adapter_parity.py:TestGeminiCliAdapterParity.test_count_tokens_fallback] + Provides a character-based token estimation for the Gemini CLI. + Uses 4 chars/token as a conservative average. + [C: tests/test_gemini_cli_adapter_parity.py:TestGeminiCliAdapterParity.test_count_tokens_fallback] """ total_chars = len("\n".join(contents)) return total_chars // 4 \ No newline at end of file diff --git a/src/hot_reloader.py b/src/hot_reloader.py index 0b3e492c..3dd0494c 100644 --- a/src/hot_reloader.py +++ b/src/hot_reloader.py @@ -67,4 +67,4 @@ class HotReloader: for name in cls.HOT_MODULES: if not cls.reload(name, app): success = False - return success \ No newline at end of file + return success