From e0d219d0dc1858c2a3afd0e6d9d8856eea43338a Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 16 May 2026 01:58:12 -0400 Subject: [PATCH] remove outdated scripts --- scripts/ai_style_formatter.py | 131 ---------- scripts/audit_unused.py | 361 ---------------------------- scripts/check_hints.py | 20 -- scripts/cleanup_tail_final.py | 12 - scripts/final_precision_inject.py | 29 --- scripts/fix_imports.py | 103 -------- scripts/fix_recursion_final.py | 62 ----- scripts/force_1space.py | 65 ----- scripts/inject_tools.py | 287 ---------------------- scripts/insert_selectable_label.py | 49 ---- scripts/migrate_personas.py | 62 ----- scripts/patch_selectable_metrics.py | 47 ---- scripts/refactor_ai_settings_2.py | 252 ------------------- scripts/refactor_ai_settings_3.py | 228 ------------------ scripts/remove_bom.py | 11 - scripts/repair_scope.py | 28 --- scripts/temp_def.py | 97 -------- scripts/temp_handle_test.py | 12 - scripts/test_font_config.py | 12 - 19 files changed, 1868 deletions(-) delete mode 100644 scripts/ai_style_formatter.py delete mode 100644 scripts/audit_unused.py delete mode 100644 scripts/check_hints.py delete mode 100644 scripts/cleanup_tail_final.py delete mode 100644 scripts/final_precision_inject.py delete mode 100644 scripts/fix_imports.py delete mode 100644 scripts/fix_recursion_final.py delete mode 100644 scripts/force_1space.py delete mode 100644 scripts/inject_tools.py delete mode 100644 scripts/insert_selectable_label.py delete mode 100644 scripts/migrate_personas.py delete mode 100644 scripts/patch_selectable_metrics.py delete mode 100644 scripts/refactor_ai_settings_2.py delete mode 100644 scripts/refactor_ai_settings_3.py delete mode 100644 scripts/remove_bom.py delete mode 100644 scripts/repair_scope.py delete mode 100644 scripts/temp_def.py delete mode 100644 scripts/temp_handle_test.py delete mode 100644 scripts/test_font_config.py diff --git a/scripts/ai_style_formatter.py b/scripts/ai_style_formatter.py deleted file mode 100644 index 0f055699..00000000 --- a/scripts/ai_style_formatter.py +++ /dev/null @@ -1,131 +0,0 @@ -from __future__ import annotations -import tokenize -import io -import os -import sys - -def format_code(source: str) -> str: - """ - Formats Python code to use exactly 1 space for indentation (including continuations), - max 1 blank line between top-level definitions, and 0 blank lines inside - function/method bodies. - """ - if not source: - return "" - try: - tokens = list(tokenize.generate_tokens(io.StringIO(source).readline)) - except tokenize.TokenError: - return source # Return as-is if it's not valid python (e.g. template files) - lines = source.splitlines(keepends=True) - num_lines = len(lines) - block_level = 0 - paren_level = 0 - in_function_stack = [] - expecting_function_indent = False - line_indent = {} - line_is_blank = {i: True for i in range(1, num_lines + 2)} - line_is_string_interior = {i: False for i in range(1, num_lines + 2)} - line_seen = set() - pending_blank_lines = [] - for tok in tokens: - t_type = tok.type - t_string = tok.string - start_line, _ = tok.start - end_line, _ = tok.end - if t_type == tokenize.STRING: - for l in range(start_line + 1, end_line + 1): - line_is_string_interior[l] = True - if t_type not in (tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT, tokenize.ENDMARKER): - for l in range(start_line, end_line + 1): - line_is_blank[l] = False - pending_blank_lines = [] - if t_type == tokenize.INDENT: - block_level += 1 - if expecting_function_indent: - in_function_stack.append(block_level) - expecting_function_indent = False - elif t_type == tokenize.DEDENT: - block_level -= 1 - if in_function_stack and block_level < in_function_stack[-1]: - in_function_stack.pop() - for l in pending_blank_lines: - line_indent[l] = block_level + paren_level - if t_string in (')', ']', '}'): - paren_level -= 1 - if start_line not in line_seen: - line_indent[start_line] = block_level + paren_level - if t_type not in (tokenize.INDENT, tokenize.DEDENT): - line_seen.add(start_line) - if t_type in (tokenize.NL, tokenize.NEWLINE): - pending_blank_lines.append(start_line) - if t_type == tokenize.NAME and t_string == 'def': - expecting_function_indent = True - if t_string in ('(', '[', '{'): - paren_level += 1 - output = [] - consecutive_blanks = 0 - for i in range(1, num_lines + 1): - if line_is_string_interior[i]: - output.append(lines[i-1]) - continue - if line_is_blank[i]: - indent = line_indent.get(i, 0) - if indent > 0: - continue - else: - if consecutive_blanks < 1: - output.append("\n") - consecutive_blanks += 1 - continue - original_line = lines[i-1] - indent = line_indent.get(i, 0) - stripped = original_line.lstrip() - is_def_start = stripped.startswith(('def ', 'class ', 'async def ', '@')) - if is_def_start and output and consecutive_blanks == 0: - prev_line = output[-1].strip() - if prev_line and not prev_line.endswith(':') and not prev_line.startswith('@'): - output.append("\n") - consecutive_blanks += 1 - consecutive_blanks = 0 - output.append(" " * indent + stripped) - if not stripped.endswith('\n') and i < num_lines: - output[-1] += '\n' - if output and not output[-1].endswith('\n'): - output[-1] += '\n' - return "".join(output) - -def process_file(file_path: str, write: bool) -> None: - try: - with open(file_path, "r", encoding="utf-8") as f: - content = f.read() - formatted = format_code(content) - if write: - if formatted != content: - with open(file_path, "w", encoding="utf-8") as f: - f.write(formatted) - print(f"Formatted: {file_path}") - else: - sys.stdout.reconfigure(encoding='utf-8') - sys.stdout.write(formatted) - except Exception as e: - print(f"Error processing {file_path}: {e}") - -def main() -> None: - import argparse - parser = argparse.ArgumentParser(description="AI-optimized Python code formatter.") - parser.add_argument("paths", nargs="+", help="Files or directories to format.") - parser.add_argument("--write", action="store_true", help="Write changes back to files.") - parser.add_argument("--exclude", nargs="*", default=[".venv", "__pycache__", ".git"], help="Directories to exclude.") - args = parser.parse_args() - for path in args.paths: - if os.path.isfile(path): - process_file(path, args.write) - elif os.path.isdir(path): - for root, dirs, files in os.walk(path): - dirs[:] = [d for d in dirs if d not in args.exclude] - for file in files: - if file.endswith(".py"): - process_file(os.path.join(root, file), args.write) - -if __name__ == "__main__": - main() diff --git a/scripts/audit_unused.py b/scripts/audit_unused.py deleted file mode 100644 index 0b731d16..00000000 --- a/scripts/audit_unused.py +++ /dev/null @@ -1,361 +0,0 @@ -import os -from pathlib import Path -import re - -# Symbols to check (extracted from previous step) -# This is a representative sample, we will process all 327. -# For the actual implementation, I'll read the output of the previous command. -raw_symbols = r""" -find_next_increment|src\aggregate.py -is_absolute_with_drive|src\aggregate.py -resolve_paths|src\aggregate.py -build_discussion_section|src\aggregate.py -build_files_section|src\aggregate.py -build_screenshots_section|src\aggregate.py -build_file_items|src\aggregate.py -build_summary_section|src\aggregate.py -build_beads_section|src\aggregate.py -build_markdown_from_items|src\aggregate.py -build_markdown_no_history|src\aggregate.py -build_discussion_text|src\aggregate.py -build_tier1_context|src\aggregate.py -build_tier2_context|src\aggregate.py -build_tier3_context|src\aggregate.py -build_markdown|src\aggregate.py -run|src\aggregate.py -main|src\aggregate.py -set_model_params|src\ai_client.py -get_history_trunc_limit|src\ai_client.py -set_history_trunc_limit|src\ai_client.py -get_current_tier|src\ai_client.py -set_current_tier|src\ai_client.py -get_comms_log_callback|src\ai_client.py -set_comms_log_callback|src\ai_client.py -set_custom_system_prompt|src\ai_client.py -set_base_system_prompt|src\ai_client.py -set_use_default_base_prompt|src\ai_client.py -set_project_context_marker|src\ai_client.py -get_combined_system_prompt|src\ai_client.py -get_comms_log|src\ai_client.py -clear_comms_log|src\ai_client.py -get_credentials_path|src\ai_client.py -ProviderError|src\ai_client.py -set_provider|src\ai_client.py -get_provider|src\ai_client.py -cleanup|src\ai_client.py -reset_session|src\ai_client.py -get_gemini_cache_stats|src\ai_client.py -list_models|src\ai_client.py -set_agent_tools|src\ai_client.py -set_tool_preset|src\ai_client.py -set_bias_profile|src\ai_client.py -get_bias_profile|src\ai_client.py -run_tier4_analysis|src\ai_client.py -run_tier4_patch_callback|src\ai_client.py -run_tier4_patch_generation|src\ai_client.py -get_token_stats|src\ai_client.py -send|src\ai_client.py -get_history_bleed_stats|src\ai_client.py -run_subagent_summarization|src\ai_client.py -HookServerInstance|src\api_hooks.py -HookHandler|src\api_hooks.py -HookServer|src\api_hooks.py -WebSocketServer|src\api_hooks.py -ApiHookClient|src\api_hook_client.py -hide_tk_root|src\app_controller.py -parse_symbols|src\app_controller.py -get_symbol_definition|src\app_controller.py -GenerateRequest|src\app_controller.py -ConfirmRequest|src\app_controller.py -ConfirmDialog|src\app_controller.py -MMAApprovalDialog|src\app_controller.py -MMASpawnApprovalDialog|src\app_controller.py -AppController|src\app_controller.py -Bead|src\beads_client.py -BeadsClient|src\beads_client.py -BackgroundShader|src\bg_shader.py -get_bg|src\bg_shader.py -generate_tickets|src\conductor_tech_lead.py -topological_sort|src\conductor_tech_lead.py -estimate_cost|src\cost_tracker.py -TrackDAG|src\dag_engine.py -ExecutionEngine|src\dag_engine.py -DiffHunk|src\diff_viewer.py -DiffFile|src\diff_viewer.py -parse_diff_header|src\diff_viewer.py -parse_hunk_header|src\diff_viewer.py -parse_diff|src\diff_viewer.py -format_diff_for_display|src\diff_viewer.py -get_line_color|src\diff_viewer.py -render_diff_text_immediate|src\diff_viewer.py -create_backup|src\diff_viewer.py -apply_patch_to_file|src\diff_viewer.py -restore_from_backup|src\diff_viewer.py -cleanup_backup|src\diff_viewer.py -EventEmitter|src\events.py -AsyncEventQueue|src\events.py -UserRequestEvent|src\events.py -ExternalEditorLauncher|src\external_editor.py -auto_detect_vscode|src\external_editor.py -get_default_launcher|src\external_editor.py -resolve_project_editor_override|src\external_editor.py -create_temp_modified_file|src\external_editor.py -ASTParser|src\file_cache.py -reset_client|src\file_cache.py -content_block_type|src\file_cache.py -get_file_id|src\file_cache.py -evict|src\file_cache.py -list_cached|src\file_cache.py -GeminiCliAdapter|src\gemini_cli_adapter.py -hide_tk_root|src\gui_2.py -vec4|src\gui_2.py -truncate_entries|src\gui_2.py -GenerateRequest|src\gui_2.py -ConfirmRequest|src\gui_2.py -App|src\gui_2.py -main|src\gui_2.py -UISnapshot|src\history.py -HistoryEntry|src\history.py -HistoryManager|src\history.py -LogPruner|src\log_pruner.py -LogRegistry|src\log_registry.py -MarkdownRenderer|src\markdown_helper.py -get_renderer|src\markdown_helper.py -render|src\markdown_helper.py -render_unindented|src\markdown_helper.py -render_code|src\markdown_helper.py -configure|src\mcp_client.py -read_file|src\mcp_client.py -list_directory|src\mcp_client.py -search_files|src\mcp_client.py -get_file_summary|src\mcp_client.py -py_get_skeleton|src\mcp_client.py -ts_c_get_skeleton|src\mcp_client.py -ts_cpp_get_skeleton|src\mcp_client.py -py_get_code_outline|src\mcp_client.py -ts_c_get_code_outline|src\mcp_client.py -ts_cpp_get_code_outline|src\mcp_client.py -ts_c_get_definition|src\mcp_client.py -ts_cpp_get_definition|src\mcp_client.py -ts_c_get_signature|src\mcp_client.py -ts_cpp_get_signature|src\mcp_client.py -ts_c_update_definition|src\mcp_client.py -ts_cpp_update_definition|src\mcp_client.py -get_file_slice|src\mcp_client.py -set_file_slice|src\mcp_client.py -edit_file|src\mcp_client.py -py_get_symbol_info|src\mcp_client.py -py_get_definition|src\mcp_client.py -py_update_definition|src\mcp_client.py -py_get_signature|src\mcp_client.py -py_set_signature|src\mcp_client.py -py_get_class_summary|src\mcp_client.py -py_get_var_declaration|src\mcp_client.py -py_set_var_declaration|src\mcp_client.py -get_git_diff|src\mcp_client.py -py_find_usages|src\mcp_client.py -py_get_imports|src\mcp_client.py -py_check_syntax|src\mcp_client.py -py_get_hierarchy|src\mcp_client.py -py_get_docstring|src\mcp_client.py -get_tree|src\mcp_client.py -derive_code_path|src\mcp_client.py -web_search|src\mcp_client.py -fetch_url|src\mcp_client.py -get_ui_performance|src\mcp_client.py -StdioMCPServer|src\mcp_client.py -ExternalMCPManager|src\mcp_client.py -get_external_mcp_manager|src\mcp_client.py -dispatch|src\mcp_client.py -async_dispatch|src\mcp_client.py -get_tool_schemas|src\mcp_client.py -load_config|src\models.py -save_config|src\models.py -parse_history_entries|src\models.py -ThinkingSegment|src\models.py -Ticket|src\models.py -Track|src\models.py -WorkerContext|src\models.py -Metadata|src\models.py -TextEditorConfig|src\models.py -ExternalEditorConfig|src\models.py -TrackState|src\models.py -FileItem|src\models.py -Preset|src\models.py -Tool|src\models.py -ToolPreset|src\models.py -BiasProfile|src\models.py -Persona|src\models.py -MCPServerConfig|src\models.py -MCPConfiguration|src\models.py -VectorStoreConfig|src\models.py -RAGConfig|src\models.py -WorkspaceProfile|src\models.py -load_mcp_config|src\models.py -WorkerPool|src\multi_agent_conductor.py -ConductorEngine|src\multi_agent_conductor.py -confirm_execution|src\multi_agent_conductor.py -confirm_spawn|src\multi_agent_conductor.py -run_worker_lifecycle|src\multi_agent_conductor.py -read_plan|src\native_orchestrator.py -write_plan|src\native_orchestrator.py -parse_plan_tasks|src\native_orchestrator.py -read_metadata|src\native_orchestrator.py -write_metadata|src\native_orchestrator.py -get_track_dir|src\native_orchestrator.py -get_archive_dir|src\native_orchestrator.py -NativeOrchestrator|src\native_orchestrator.py -get_track_history_summary|src\orchestrator_pm.py -generate_tracks|src\orchestrator_pm.py -CodeOutliner|src\outline_tool.py -get_outline|src\outline_tool.py -PendingPatch|src\patch_modal.py -PatchModalManager|src\patch_modal.py -get_patch_modal_manager|src\patch_modal.py -reset_patch_modal_manager|src\patch_modal.py -get_config_path|src\paths.py -get_global_presets_path|src\paths.py -get_project_presets_path|src\paths.py -get_global_tool_presets_path|src\paths.py -get_project_tool_presets_path|src\paths.py -get_global_personas_path|src\paths.py -get_project_personas_path|src\paths.py -get_global_workspace_profiles_path|src\paths.py -get_project_workspace_profiles_path|src\paths.py -get_conductor_dir|src\paths.py -get_logs_dir|src\paths.py -get_scripts_dir|src\paths.py -get_tracks_dir|src\paths.py -get_track_state_dir|src\paths.py -get_archive_dir|src\paths.py -get_full_path_info|src\paths.py -reset_resolved|src\paths.py -PerformanceScope|src\performance_monitor.py -get_monitor|src\performance_monitor.py -PerformanceMonitor|src\performance_monitor.py -PersonaManager|src\personas.py -PresetManager|src\presets.py -now_ts|src\project_manager.py -parse_ts|src\project_manager.py -entry_to_str|src\project_manager.py -str_to_entry|src\project_manager.py -get_git_commit|src\project_manager.py -get_git_log|src\project_manager.py -default_discussion|src\project_manager.py -default_project|src\project_manager.py -get_history_path|src\project_manager.py -load_project|src\project_manager.py -load_history|src\project_manager.py -clean_nones|src\project_manager.py -save_project|src\project_manager.py -migrate_from_legacy_config|src\project_manager.py -flat_config|src\project_manager.py -save_track_state|src\project_manager.py -load_track_state|src\project_manager.py -load_track_history|src\project_manager.py -save_track_history|src\project_manager.py -get_all_tracks|src\project_manager.py -calculate_track_progress|src\project_manager.py -branch_discussion|src\project_manager.py -promote_take|src\project_manager.py -BaseEmbeddingProvider|src\rag_engine.py -LocalEmbeddingProvider|src\rag_engine.py -GeminiEmbeddingProvider|src\rag_engine.py -RAGEngine|src\rag_engine.py -open_session|src\session_logger.py -close_session|src\session_logger.py -reset_session|src\session_logger.py -log_api_hook|src\session_logger.py -log_comms|src\session_logger.py -log_tool_call|src\session_logger.py -log_tool_output|src\session_logger.py -log_cli_call|src\session_logger.py -draw_soft_shadow|src\shaders.py -apply_faux_acrylic_glass|src\shaders.py -ShaderManager|src\shader_manager.py -run_powershell|src\shell_runner.py -summarise_file|src\summarize.py -summarise_items|src\summarize.py -build_summary_markdown|src\summarize.py -get_file_hash|src\summary_cache.py -SummaryCache|src\summary_cache.py -format_takes_diff|src\synthesis_formatter.py -get_palette_names|src\theme.py -get_current_palette|src\theme.py -get_current_font_path|src\theme.py -get_current_font_size|src\theme.py -get_current_scale|src\theme.py -get_shader_config|src\theme.py -get_window_frame_config|src\theme.py -get_palette_colours|src\theme.py -apply|src\theme.py -apply_font|src\theme.py -set_scale|src\theme.py -save_to_config|src\theme.py -load_from_config|src\theme.py -is_nerv_active|src\theme_2.py -get_transparency|src\theme_2.py -set_transparency|src\theme_2.py -get_child_transparency|src\theme_2.py -set_child_transparency|src\theme_2.py -apply_current|src\theme_2.py -get_font_loading_params|src\theme_2.py -get_tweaked_theme|src\theme_2.py -apply_nerv|src\theme_nerv.py -CRTFilter|src\theme_nerv_fx.py -StatusFlicker|src\theme_nerv_fx.py -AlertPulsing|src\theme_nerv_fx.py -parse_thinking_trace|src\thinking_parser.py -ToolBiasEngine|src\tool_bias.py -ToolPresetManager|src\tool_presets.py -WorkspaceManager|src\workspace_manager.py -AISettingsSimulation|simulation\sim_ai_settings.py -BaseSimulation|simulation\sim_base.py -run_sim|simulation\sim_base.py -ContextSimulation|simulation\sim_context.py -ExecutionSimulation|simulation\sim_execution.py -ToolsSimulation|simulation\sim_tools.py -UserSimAgent|simulation\user_agent.py -WorkflowSimulator|simulation\workflow_sim.py -""" - -symbols = [] -for line in raw_symbols.strip().split("\n"): - if "|" in line: - name, path = line.split("|") - symbols.append((name.strip(), path.strip())) - -# Load all project source -source_files = {} -for root in ['src', 'simulation']: - for p in Path(root).rglob('*.py'): - try: - source_files[str(p)] = p.read_text(encoding='utf-8') - except Exception: - pass - -unused = [] -for name, path in symbols: - # Skip generic names that might give false positives in a simple regex search - if name in ["run", "main", "apply", "save_config", "load_config", "configure"]: - continue - - pattern = re.compile(r'\b' + re.escape(name) + r'\b') - count = 0 - for fpath, code in source_files.items(): - if fpath == path: - # Only count if it appears more than once (one for definition) - # This is a bit naive for methods vs standalone functions but a good start - matches = pattern.findall(code) - if len(matches) > 1: - count += (len(matches) - 1) - else: - matches = pattern.findall(code) - count += len(matches) - - if count == 0: - unused.append((name, path)) - -print(f"TOTAL_UNUSED:{len(unused)}") -for name, path in unused: - print(f"UNUSED:{name}|PATH:{path}") diff --git a/scripts/check_hints.py b/scripts/check_hints.py deleted file mode 100644 index 4711e904..00000000 --- a/scripts/check_hints.py +++ /dev/null @@ -1,20 +0,0 @@ - -files = ['ai_client.py', 'aggregate.py', 'mcp_client.py', 'shell_runner.py'] -for file_path in files: - print(f"Checking {file_path}...") - with open(file_path, 'r', encoding='utf-8') as f: - lines = f.readlines() - for i, line in enumerate(lines): - if line.strip().startswith('def '): - if '->' not in line: - # Check next line if it's a multiline def - if '):' not in line: - full_def = line - j = i + 1 - while j < len(lines) and '):' not in lines[j-1]: - full_def += lines[j] - j += 1 - if '->' not in full_def: - print(f" Missing hint at line {i+1}: {line.strip()}") - else: - print(f" Missing hint at line {i+1}: {line.strip()}") diff --git a/scripts/cleanup_tail_final.py b/scripts/cleanup_tail_final.py deleted file mode 100644 index b06ace60..00000000 --- a/scripts/cleanup_tail_final.py +++ /dev/null @@ -1,12 +0,0 @@ -from pathlib import Path -import re - -file_path = Path('src/app_controller.py') -code = file_path.read_text(encoding='utf-8') - -# Remove the garbage tail -code = re.sub(r'\n= \[\]\s*$', '', code) -code = code.strip() + "\n" - -file_path.write_text(code, encoding='utf-8') -print("Tail cleanup complete.") diff --git a/scripts/final_precision_inject.py b/scripts/final_precision_inject.py deleted file mode 100644 index 823a0f99..00000000 --- a/scripts/final_precision_inject.py +++ /dev/null @@ -1,29 +0,0 @@ -from pathlib import Path -import re - -file_path = Path('src/app_controller.py') -code = file_path.read_text(encoding='utf-8') - -# 1. Inject show_windows -code = re.sub( - r'(self\._pending_gui_tasks_lock: threading\.Lock = threading\.Lock\(\))', - r'\1\n self.show_windows: Dict[str, bool] = {}', - code -) - -# 2. Inject ui_active_persona and ui_active_bias_profile -code = re.sub( - r'(self\.ui_ai_input: str = "")', - r'self.ui_active_persona: str = ""\n self.ui_active_bias_profile: str | None = None\n \1', - code -) - -# 3. Add ui_active_persona to _settable_fields -code = re.sub( - r"('disc_new_role_input': 'ui_disc_new_role_input',)", - r"\1\n 'active_persona': 'ui_active_persona',", - code -) - -file_path.write_text(code, encoding='utf-8') -print("Precision injection complete.") diff --git a/scripts/fix_imports.py b/scripts/fix_imports.py deleted file mode 100644 index 0f6f4380..00000000 --- a/scripts/fix_imports.py +++ /dev/null @@ -1,103 +0,0 @@ -import ast -import sys -import pathlib - -class ImportCollector(ast.NodeTransformer): - def __init__(self): - self.collected_imports = [] - - def visit_Import(self, node): - self.collected_imports.append(node) - return None - - def visit_ImportFrom(self, node): - self.collected_imports.append(node) - return None - -class PassFiller(ast.NodeTransformer): - """Ensures that blocks that became empty after import removal have a 'pass' statement.""" - def generic_visit(self, node): - super().generic_visit(node) - if hasattr(node, 'body') and isinstance(node.body, list) and not node.body: - if not isinstance(node, ast.Module): - node.body.append(ast.Pass()) - return node - -def fix_imports(file_path): - path = pathlib.Path(file_path) - if not path.exists(): - print(f"File not found: {file_path}") - return - - try: - content = path.read_text(encoding='utf-8') - tree = ast.parse(content) - except Exception as e: - print(f"Error parsing {file_path}: {e}") - return - - collector = ImportCollector() - tree = collector.visit(tree) - - # Fill empty bodies with pass - tree = PassFiller().visit(tree) - - if not collector.collected_imports: - print(f"No imports to move in {file_path}") - return - - # De-duplicate while preserving order - unique_imports = {} - for node in collector.collected_imports: - try: - # We use unparse to identify identical imports - code = ast.unparse(node).strip() - if code not in unique_imports: - unique_imports[code] = node - except: - continue - - if not unique_imports: - return - - # Sort: __future__ first, then others - future_imports = [] - other_imports = [] - for code, node in unique_imports.items(): - if isinstance(node, ast.ImportFrom) and node.module == '__future__': - future_imports.append(node) - else: - other_imports.append(node) - - all_to_insert = future_imports + other_imports - - # Find insertion point (after initial docstring) - insertion_idx = 0 - if tree.body: - first = tree.body[0] - if (isinstance(first, ast.Expr) and - isinstance(first.value, ast.Constant) and - isinstance(first.value.value, str)): - insertion_idx = 1 - - # Insert imports - for i, node in enumerate(all_to_insert): - tree.body.insert(insertion_idx + i, node) - - try: - new_code = ast.unparse(tree) - # Basic check to avoid unnecessary writes - if new_code.strip() != content.strip(): - path.write_text(new_code, encoding='utf-8') - print(f"Updated {file_path}") - else: - print(f"No changes for {file_path}") - except Exception as e: - print(f"Error unparsing or writing {file_path}: {e}") - -if __name__ == "__main__": - if len(sys.argv) < 2: - print("Usage: python scripts/fix_imports.py ...") - else: - for arg in sys.argv[1:]: - fix_imports(arg) diff --git a/scripts/fix_recursion_final.py b/scripts/fix_recursion_final.py deleted file mode 100644 index 77691520..00000000 --- a/scripts/fix_recursion_final.py +++ /dev/null @@ -1,62 +0,0 @@ -from pathlib import Path -import re - -# Fix AppController -file_ac = Path('src/app_controller.py') -code_ac = file_ac.read_text(encoding='utf-8') -# Robust non-recursive __getattr__ -new_getattr_ac = """ def __getattr__(self, name: str) -> Any: - if name == '_app': - raise AttributeError(name) - # Check if _app exists in self without triggering __getattr__ - try: - app = object.__getattribute__(self, '_app') - except AttributeError: - raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") - - if app is not None and name in app.__dict__: - return getattr(app, name) - raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") -""" -# Replace all instances of __getattr__ in AppController (in case of duplication) -code_ac = re.sub(r'def __getattr__\(self, name: str\) -> Any:.*?raise AttributeError\(.*?\)', new_getattr_ac, code_ac, flags=re.DOTALL) -file_ac.write_text(code_ac, encoding='utf-8') - -# Fix App -file_gui = Path('src/gui_2.py') -code_gui = file_gui.read_text(encoding='utf-8') - -new_getattr_gui = """ def __getattr__(self, name: str) -> Any: - if name == 'controller': - raise AttributeError(name) - try: - ctrl = object.__getattribute__(self, 'controller') - except AttributeError: - raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") - - if ctrl is not None and name in ctrl.__dict__: - return getattr(ctrl, name) - raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") -""" -code_gui = re.sub(r'def __getattr__\(self, name: str\) -> Any:.*?raise AttributeError\(.*?\)', new_getattr_gui, code_gui, flags=re.DOTALL) - -new_setattr_gui = """ def __setattr__(self, name: str, value: Any) -> None: - if name == 'controller': - object.__setattr__(self, name, value) - return - - try: - ctrl = object.__getattribute__(self, 'controller') - except AttributeError: - ctrl = None - - if ctrl is not None and name in ctrl.__dict__: - setattr(ctrl, name, value) - else: - object.__setattr__(self, name, value) -""" -code_gui = re.sub(r'def __setattr__\(self, name: str, value: Any\) -> None:.*?object\.__setattr__\(self, name, value\)', new_setattr_gui, code_gui, flags=re.DOTALL) - -file_gui.write_text(code_gui, encoding='utf-8') - -print('Delegation fix complete.') diff --git a/scripts/force_1space.py b/scripts/force_1space.py deleted file mode 100644 index 12eccad7..00000000 --- a/scripts/force_1space.py +++ /dev/null @@ -1,65 +0,0 @@ -import tokenize -import io -import sys -import os - -def force_1space(path): - try: - with open(path, 'rb') as f: - content = f.read() - tokens = list(tokenize.tokenize(io.BytesIO(content).readline)) - except Exception: - return - - col_to_level = {0: 0} - level = 0 - for tok in tokens: - if tok.type == tokenize.INDENT: - level += 1 - col_to_level[tok.end[1]] = level - elif tok.type == tokenize.DEDENT: - level -= 1 - - new_content = [] - level = 0 - last_line = -1 - last_end = (1, 0) - - for tok in tokens: - if tok.type == tokenize.ENCODING: - continue - if tok.type == tokenize.ENDMARKER: - break - - if tok.type == tokenize.INDENT: - level += 1 - continue - if tok.type == tokenize.DEDENT: - level -= 1 - continue - - if tok.start[0] > last_line: - if tok.type not in (tokenize.NEWLINE, tokenize.NL): - if tok.type == tokenize.COMMENT: - actual_level = col_to_level.get(tok.start[1], level) - else: - actual_level = level - new_content.append(" " * actual_level) - new_content.append(tok.string) - else: - new_content.append(tok.string) - last_line = tok.start[0] - last_end = tok.end - else: - if tok.start[1] > last_end[1]: - new_content.append(" " * (tok.start[1] - last_end[1])) - new_content.append(tok.string) - last_end = tok.end - - with open(path, 'w', encoding='utf-8') as f: - f.write("".join(new_content)) - -if __name__ == "__main__": - for arg in sys.argv[1:]: - if os.path.isfile(arg): - force_1space(arg) diff --git a/scripts/inject_tools.py b/scripts/inject_tools.py deleted file mode 100644 index e8dba6b9..00000000 --- a/scripts/inject_tools.py +++ /dev/null @@ -1,287 +0,0 @@ -import re - -with open('mcp_client.py', 'r', encoding='utf-8') as f: - content: str = f.read() - # 1. Add import os if not there -if 'import os' not in content: - content: str = content.replace('import summarize', 'import os\nimport summarize') - # 2. Add the functions before "# ------------------------------------------------------------------ web tools" -functions_code: str = r''' -def py_find_usages(path: str, name: str) -> str: - """Finds exact string matches of a symbol in a given file or directory.""" - p, err = _resolve_and_check(path) - if err: return err - try: - import re - pattern = re.compile(r"\b" + re.escape(name) + r"\b") - results = [] - def _search_file(fp): - if fp.name == "history.toml" or fp.name.endswith("_history.toml"): return - if not _is_allowed(fp): return - try: - text = fp.read_text(encoding="utf-8") - lines = text.splitlines() - for i, line in enumerate(lines, 1): - if pattern.search(line): - rel = fp.relative_to(_primary_base_dir if _primary_base_dir else Path.cwd()) - results.append(f"{rel}:{i}: {line.strip()[:100]}") - except Exception: - pass - - if p.is_file(): - _search_file(p) - else: - for root, dirs, files in os.walk(p): - dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ('__pycache__', 'venv', 'env')] - for file in files: - if file.endswith(('.py', '.md', '.toml', '.txt', '.json')): - _search_file(Path(root) / file) - - if not results: - return f"No usages found for '{name}' in {p}" - if len(results) > 100: - return "\n".join(results[:100]) + f"\n... (and {len(results)-100} more)" - return "\n".join(results) - except Exception as e: - return f"ERROR finding usages for '{name}': {e}" - -def py_get_imports(path: str) -> str: - """Parses a file's AST and returns a strict list of its dependencies.""" - p, err = _resolve_and_check(path) - if err: return err - if not p.is_file() or p.suffix != ".py": return f"ERROR: not a python file: {path}" - try: - import ast - code = p.read_text(encoding="utf-8") - tree = ast.parse(code) - imports = [] - for node in tree.body: - if isinstance(node, ast.Import): - for alias in node.names: - imports.append(alias.name) - elif isinstance(node, ast.ImportFrom): - module = node.module or "" - for alias in node.names: - imports.append(f"{module}.{alias.name}" if module else alias.name) - if not imports: return "No imports found." - return "Imports:\n" + "\n".join(f" - {i}" for i in imports) - except Exception as e: - return f"ERROR getting imports for '{path}': {e}" - -def py_check_syntax(path: str) -> str: - """Runs a quick syntax check on a Python file.""" - p, err = _resolve_and_check(path) - if err: return err - if not p.is_file() or p.suffix != ".py": return f"ERROR: not a python file: {path}" - try: - import ast - code = p.read_text(encoding="utf-8") - ast.parse(code) - return f"Syntax OK: {path}" - except SyntaxError as e: - return f"SyntaxError in {path} at line {e.lineno}, offset {e.offset}: {e.msg}\n{e.text}" - except Exception as e: - return f"ERROR checking syntax for '{path}': {e}" - -def py_get_hierarchy(path: str, class_name: str) -> str: - """Scans the project to find subclasses of a given class.""" - p, err = _resolve_and_check(path) - if err: return err - import ast - subclasses = [] - - def _search_file(fp): - if not _is_allowed(fp): return - try: - code = fp.read_text(encoding="utf-8") - tree = ast.parse(code) - for node in ast.walk(tree): - if isinstance(node, ast.ClassDef): - for base in node.bases: - if isinstance(base, ast.Name) and base.id == class_name: - subclasses.append(f"{fp.name}: class {node.name}({class_name})") - elif isinstance(base, ast.Attribute) and base.attr == class_name: - subclasses.append(f"{fp.name}: class {node.name}({base.value.id}.{class_name})") - except Exception: - pass - - try: - if p.is_file(): - _search_file(p) - else: - for root, dirs, files in os.walk(p): - dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ('__pycache__', 'venv', 'env')] - for file in files: - if file.endswith('.py'): - _search_file(Path(root) / file) - - if not subclasses: - return f"No subclasses of '{class_name}' found in {p}" - return f"Subclasses of '{class_name}':\n" + "\n".join(f" - {s}" for s in subclasses) - except Exception as e: - return f"ERROR finding subclasses of '{class_name}': {e}" - -def py_get_docstring(path: str, name: str) -> str: - """Extracts the docstring for a specific module, class, or function.""" - p, err = _resolve_and_check(path) - if err: return err - if not p.is_file() or p.suffix != ".py": return f"ERROR: not a python file: {path}" - try: - import ast - code = p.read_text(encoding="utf-8") - tree = ast.parse(code) - if not name or name == "module": - doc = ast.get_docstring(tree) - return doc if doc else "No module docstring found." - - node = _get_symbol_node(tree, name) - if not node: return f"ERROR: could not find symbol '{name}' in {path}" - doc = ast.get_docstring(node) - return doc if doc else f"No docstring found for '{name}'." - except Exception as e: - return f"ERROR getting docstring for '{name}': {e}" - -def get_tree(path: str, max_depth: int = 2) -> str: - """Returns a directory structure up to a max depth.""" - p, err = _resolve_and_check(path) - if err: return err - if not p.is_dir(): return f"ERROR: not a directory: {path}" - - try: - max_depth = int(max_depth) - def _build_tree(dir_path, current_depth, prefix=""): - if current_depth > max_depth: return [] - lines = [] - try: - entries = sorted(dir_path.iterdir(), key=lambda e: (e.is_file(), e.name.lower())) - except PermissionError: - return [] - - # Filter - entries = [e for e in entries if not e.name.startswith('.') and e.name not in ('__pycache__', 'venv', 'env') and e.name != "history.toml" and not e.name.endswith("_history.toml")] - - for i, entry in enumerate(entries): - is_last = (i == len(entries) - 1) - connector = "└── " if is_last else "├── " - lines.append(f"{prefix}{connector}{entry.name}") - if entry.is_dir(): - extension = " " if is_last else "│ " - lines.extend(_build_tree(entry, current_depth + 1, prefix + extension)) - return lines - - tree_lines = [f"{p.name}/"] + _build_tree(p, 1) - return "\n".join(tree_lines) - except Exception as e: - return f"ERROR generating tree for '{path}': {e}" - -# ------------------------------------------------------------------ web tools''' - -content: str = content.replace('# ------------------------------------------------------------------ web tools', functions_code) - -# 3. Update TOOL_NAMES -old_tool_names_match: re.Match | None = re.search(r'TOOL_NAMES\s*=\s*\{([^}]*)\}', content) -if old_tool_names_match: - old_names: str = old_tool_names_match.group(1) - new_names: str = old_names + ', "py_find_usages", "py_get_imports", "py_check_syntax", "py_get_hierarchy", "py_get_docstring", "get_tree"' - content: str = content.replace(old_tool_names_match.group(0), f'TOOL_NAMES = {{{new_names}}}') - # 4. Update dispatch -dispatch_additions: str = r''' - if tool_name == "py_find_usages": - return py_find_usages(tool_input.get("path", ""), tool_input.get("name", "")) - if tool_name == "py_get_imports": - return py_get_imports(tool_input.get("path", "")) - if tool_name == "py_check_syntax": - return py_check_syntax(tool_input.get("path", "")) - if tool_name == "py_get_hierarchy": - return py_get_hierarchy(tool_input.get("path", ""), tool_input.get("class_name", "")) - if tool_name == "py_get_docstring": - return py_get_docstring(tool_input.get("path", ""), tool_input.get("name", "")) - if tool_name == "get_tree": - return get_tree(tool_input.get("path", ""), tool_input.get("max_depth", 2)) - return f"ERROR: unknown MCP tool '{tool_name}'" -''' -content: str = re.sub( - r' return f"ERROR: unknown MCP tool \'{tool_name}\'"', dispatch_additions.strip(), content) - -# 5. Update MCP_TOOL_SPECS -mcp_tool_specs_addition: str = r''' - { - "name": "py_find_usages", - "description": "Finds exact string matches of a symbol in a given file or directory.", - "parameters": { - "type": "object", - "properties": { - "path": { "type": "string", "description": "Path to file or directory to search." }, - "name": { "type": "string", "description": "The symbol/string to search for." } - }, - "required": ["path", "name"] - } - }, - { - "name": "py_get_imports", - "description": "Parses a file's AST and returns a strict list of its dependencies.", - "parameters": { - "type": "object", - "properties": { - "path": { "type": "string", "description": "Path to the .py file." } - }, - "required": ["path"] - } - }, - { - "name": "py_check_syntax", - "description": "Runs a quick syntax check on a Python file.", - "parameters": { - "type": "object", - "properties": { - "path": { "type": "string", "description": "Path to the .py file." } - }, - "required": ["path"] - } - }, - { - "name": "py_get_hierarchy", - "description": "Scans the project to find subclasses of a given class.", - "parameters": { - "type": "object", - "properties": { - "path": { "type": "string", "description": "Directory path to search in." }, - "class_name": { "type": "string", "description": "Name of the base class." } - }, - "required": ["path", "class_name"] - } - }, - { - "name": "py_get_docstring", - "description": "Extracts the docstring for a specific module, class, or function.", - "parameters": { - "type": "object", - "properties": { - "path": { "type": "string", "description": "Path to the .py file." }, - "name": { "type": "string", "description": "Name of symbol or 'module' for the file docstring." } - }, - "required": ["path", "name"] - } - }, - { - "name": "get_tree", - "description": "Returns a directory structure up to a max depth.", - "parameters": { - "type": "object", - "properties": { - "path": { "type": "string", "description": "Directory path." }, - "max_depth": { "type": "integer", "description": "Maximum depth to recurse (default 2)." } - }, - "required": ["path"] - } - } -] -''' - -content: str = re.sub( - r'\]\s*$', mcp_tool_specs_addition.strip(), content) - -with open('mcp_client.py', 'w', encoding='utf-8') as f: - f.write(content) - -print("Injected new tools.") diff --git a/scripts/insert_selectable_label.py b/scripts/insert_selectable_label.py deleted file mode 100644 index 0621be51..00000000 --- a/scripts/insert_selectable_label.py +++ /dev/null @@ -1,49 +0,0 @@ - -import sys - -def insert_method(file_path): - with open(file_path, 'r', encoding='utf-8', newline='') as f: - lines = f.readlines() - - target_line = -1 - for i, line in enumerate(lines): - if 'def _render_heavy_text' in line: - # Find the end of this method - for j in range(i + 1, len(lines)): - if lines[j].startswith(' def '): - target_line = j - break - if target_line != -1: - break - - if target_line == -1: - print("Could not find insertion point") - sys.exit(1) - - new_method = [ - '\n', - ' def _render_selectable_label(self, label: str, value: str, width: float = 0.0, multiline: bool = False, height: float = 0.0, color: Optional[imgui.ImVec4] = None) -> None:\n', - ' imgui.push_id(label + str(hash(value)))\n', - ' pops = 2\n', - ' imgui.push_style_color(imgui.Col_.frame_bg, vec4(0, 0, 0, 0))\n', - ' imgui.push_style_color(imgui.Col_.border, vec4(0, 0, 0, 0))\n', - ' if color:\n', - ' imgui.push_style_color(imgui.Col_.text, color)\n', - ' pops += 1\n', - ' if multiline:\n', - ' imgui.input_text_multiline("##" + label, value, imgui.ImVec2(width, height), imgui.InputTextFlags_.read_only)\n', - ' else:\n', - ' if width > 0: imgui.set_next_item_width(width)\n', - ' imgui.input_text("##" + label, value, imgui.InputTextFlags_.read_only)\n', - ' imgui.pop_style_color(pops)\n', - ' imgui.pop_id()\n' - ] - - lines[target_line:target_line] = new_method - - with open(file_path, 'w', encoding='utf-8', newline='') as f: - f.writelines(lines) - print("Successfully inserted _render_selectable_label") - -if __name__ == "__main__": - insert_method("src/gui_2.py") diff --git a/scripts/migrate_personas.py b/scripts/migrate_personas.py deleted file mode 100644 index 9ba8a038..00000000 --- a/scripts/migrate_personas.py +++ /dev/null @@ -1,62 +0,0 @@ -import os -import sys -from pathlib import Path -from src import models -from src.paths import get_config_path, get_global_presets_path, get_project_presets_path -from src.presets import PresetManager -from src.personas import PersonaManager - -def migrate(): - print("Starting Persona Migration...") - - config_path = get_config_path() - try: - with open(config_path, "rb") as f: - import tomllib - config = tomllib.load(f) - except Exception as e: - print(f"Could not load config: {e}") - return - - ai_cfg = config.get("ai", {}) - provider = ai_cfg.get("provider") - model = ai_cfg.get("model") - - global_presets_path = get_global_presets_path() - preset_manager = PresetManager() - - persona_manager = PersonaManager() - - # Migrate global presets - if global_presets_path.exists(): - global_data = preset_manager._load_file(global_presets_path) - for name, data in global_data.get("presets", {}).items(): - preset = models.Preset.from_dict(name, data) - persona = models.Persona( - name=name, - preferred_models=[{"provider": provider, "model": model}], - system_prompt=preset.system_prompt - ) - persona_manager.save_persona(persona, scope="global") - print(f"Migrated global preset to persona: {name}") - - # Create Initial Legacy Persona from config if not in presets - active_preset = ai_cfg.get("active_preset") - if active_preset and active_preset not in persona_manager.load_all(): - persona = models.Persona( - name=active_preset, - preferred_models=[{ - "provider": provider, - "model": model, - "temperature": ai_cfg.get("temperature"), - "max_output_tokens": ai_cfg.get("max_tokens") - }], - system_prompt=ai_cfg.get("system_prompt", "") - ) - persona_manager.save_persona(persona, scope="global") - print(f"Created Initial Legacy persona from active_preset: {active_preset}") - - print("Migration complete.") - -if __name__ == "__main__": - migrate() diff --git a/scripts/patch_selectable_metrics.py b/scripts/patch_selectable_metrics.py deleted file mode 100644 index 1cda93ac..00000000 --- a/scripts/patch_selectable_metrics.py +++ /dev/null @@ -1,47 +0,0 @@ - -import sys -import re - -def patch_gui(file_path): - with open(file_path, 'r', encoding='utf-8', newline='') as f: - content = f.read() - - # 1. Patch _render_provider_panel Session ID - content = content.replace( - ' imgui.text(f"Session ID: {sid}")', - ' imgui.text("Session ID:"); imgui.same_line(); self._render_selectable_label("gemini_cli_sid", sid, width=200)' - ) - - # 2. Patch _render_token_budget_panel Session Telemetry - content = content.replace( - ' imgui.text_colored(C_RES, f"Tokens: {total:,} (In: {usage[\'input_tokens\']:,} Out: {usage[\'output_tokens\']:,})")', - ' self._render_selectable_label("session_telemetry_tokens", f"Tokens: {total:,} (In: {usage[\'input_tokens\']:,} Out: {usage[\'output_tokens\']:,})", width=-1, color=C_RES)' - ) - - # 3. Patch _render_token_budget_panel MMA Tier Costs table - # This is trickier, let's find the loop - tier_table_pattern = re.compile( - r'(for tier, stats in self\.mma_tier_usage\.items\(\):\s+.*?imgui\.table_set_column_index\(0\); )imgui\.text\(tier\)(\s+imgui\.table_set_column_index\(1\); )imgui\.text\(model\.split\(\'-\'\)\[0\]\)(\s+imgui\.table_set_column_index\(2\); )imgui\.text\(f"\{tokens:,\}"\)(\s+imgui\.table_set_column_index\(3\); )imgui\.text_colored\(imgui\.ImVec4\(0\.2, 0\.9, 0\.2, 1\), f"\$\{cost:\.4f\}"\)', - re.DOTALL - ) - - def tier_replacement(match): - return (match.group(1) + 'self._render_selectable_label(f"tier_{tier}", tier, width=-1)' + - match.group(2) + 'self._render_selectable_label(f"model_{tier}", model.split("-")[0], width=-1)' + - match.group(3) + 'self._render_selectable_label(f"tokens_{tier}", f"{tokens:,}", width=-1)' + - match.group(4) + 'self._render_selectable_label(f"cost_{tier}", f"${cost:.4f}", width=-1, color=imgui.ImVec4(0.2, 0.9, 0.2, 1))') - - content = tier_table_pattern.sub(tier_replacement, content) - - # 4. Patch _render_token_budget_panel Session Total - content = content.replace( - ' imgui.text_colored(imgui.ImVec4(0, 1, 0, 1), f"Session Total: ${tier_total:.4f}")', - ' self._render_selectable_label("session_total_cost", f"Session Total: ${tier_total:.4f}", width=-1, color=imgui.ImVec4(0, 1, 0, 1))' - ) - - with open(file_path, 'w', encoding='utf-8', newline='') as f: - f.write(content) - print("Successfully patched src/gui_2.py for selectable metrics") - -if __name__ == "__main__": - patch_gui("src/gui_2.py") diff --git a/scripts/refactor_ai_settings_2.py b/scripts/refactor_ai_settings_2.py deleted file mode 100644 index 9b37c32a..00000000 --- a/scripts/refactor_ai_settings_2.py +++ /dev/null @@ -1,252 +0,0 @@ -import sys - -with open("src/gui_2.py", "r", encoding="utf-8") as f: - content = f.read() - -# 1. In _render_provider_panel, remove Fetch Models -old_fetch = """ imgui.text("Model") - imgui.same_line() - if imgui.button("Fetch Models"): - self._fetch_models(self.current_provider) - if imgui.begin_list_box("##models", imgui.ImVec2(-1, 120)):""" -new_fetch = """ imgui.text("Model") - if imgui.begin_list_box("##models", imgui.ImVec2(-1, 120)):""" -content = content.replace(old_fetch, new_fetch) - -# 2. Extract Persona block -# We need to find the start of 'imgui.text("Persona")' and end of 'self._editing_persona_is_new = True' -# Let's be very careful. -old_persona_block = """ imgui.text("Persona") - if not hasattr(self, 'ui_active_persona'): - self.ui_active_persona = "" - personas = getattr(self.controller, 'personas', {}) - if imgui.begin_combo("##persona", self.ui_active_persona or "None"): - if imgui.selectable("None", not self.ui_active_persona)[0]: - self.ui_active_persona = "" - for pname in sorted(personas.keys()): - if imgui.selectable(pname, pname == self.ui_active_persona)[0]: - self.ui_active_persona = pname - if pname in personas: - persona = personas[pname] - self._editing_persona_name = persona.name - self._editing_persona_provider = persona.provider or "" - self._editing_persona_model = persona.model or "" - self._editing_persona_system_prompt = persona.system_prompt or "" - self._editing_persona_temperature = persona.temperature or 0.7 - self._editing_persona_max_tokens = persona.max_output_tokens or 4096 - self._editing_persona_tool_preset_id = persona.tool_preset or "" - self._editing_persona_bias_profile_id = persona.bias_profile or "" - import json - self._editing_persona_preferred_models = json.dumps(persona.preferred_models) if persona.preferred_models else "[]" - self._editing_persona_is_new = False - if persona.provider and persona.provider in self.controller.PROVIDERS: - self.current_provider = persona.provider - if persona.model: - self.current_model = persona.model - if persona.temperature is not None: - ai_client.temperature = persona.temperature - if persona.max_output_tokens: - ai_client.max_output_tokens = persona.max_output_tokens - if persona.system_prompt: - ai_client.system_instruction = persona.system_prompt - if persona.tool_preset: - self.ui_active_tool_preset = persona.tool_preset - ai_client.set_tool_preset(persona.tool_preset) - if persona.bias_profile: - self.ui_active_bias_profile = persona.bias_profile - ai_client.set_bias_profile(persona.bias_profile) - imgui.end_combo() - imgui.same_line() - if imgui.button("Manage Personas"): - self.show_persona_editor_window = True - if self.ui_active_persona and self.ui_active_persona in personas: - persona = personas[self.ui_active_persona] - self._editing_persona_name = persona.name - self._editing_persona_provider = persona.provider or "" - self._editing_persona_model = persona.model or "" - self._editing_persona_system_prompt = persona.system_prompt or "" - self._editing_persona_temperature = persona.temperature if persona.temperature is not None else 0.7 - self._editing_persona_max_tokens = persona.max_output_tokens if persona.max_output_tokens is not None else 4096 - self._editing_persona_tool_preset_id = persona.tool_preset or "" - self._editing_persona_bias_profile_id = persona.bias_profile or "" - self._editing_persona_preferred_models_list = list(persona.preferred_models) if persona.preferred_models else [] - self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(persona.name) - self._editing_persona_is_new = False - else: - self._editing_persona_name = "" - self._editing_persona_provider = self.current_provider - self._editing_persona_model = self.current_model - self._editing_persona_system_prompt = "" - self._editing_persona_temperature = 0.7 - self._editing_persona_max_tokens = 4096 - self._editing_persona_tool_preset_id = "" - self._editing_persona_bias_profile_id = "" - self._editing_persona_preferred_models_list = [] - self._editing_persona_scope = "project" - self._editing_persona_is_new = True""" - -# We need to extract the bias profile block as well -old_bias_block = """ imgui.text("Bias Profile") - if imgui.begin_combo("##bias", self.ui_active_bias_profile or "None"): - if imgui.selectable("None", not self.ui_active_bias_profile)[0]: - self.ui_active_bias_profile = "" - ai_client.set_bias_profile(None) - for bname in sorted(self.bias_profiles.keys()): - if imgui.selectable(bname, bname == self.ui_active_bias_profile)[0]: - self.ui_active_bias_profile = bname - ai_client.set_bias_profile(bname) - imgui.end_combo()""" - -# Remove them from their original spots -content = content.replace(old_bias_block, "") -content = content.replace(old_persona_block, "") - -# Insert Persona block at the top of _render_provider_panel -old_provider_start = """ def _render_provider_panel(self) -> None: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") - imgui.text("Provider")""" -new_provider_start = f""" def _render_provider_panel(self) -> None: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") -{old_persona_block} - imgui.separator() - imgui.text("Provider")""" -content = content.replace(old_provider_start, new_provider_start) - -# Update _render_agent_tools_panel -old_agent_tools_start = """ def _render_agent_tools_panel(self) -> None: - imgui.text_colored(C_LBL, 'Active Tool Preset')""" -new_agent_tools_start = f""" def _render_agent_tools_panel(self) -> None: - if imgui.collapsing_header("Active Tool Presets & Biases", imgui.TreeNodeFlags_.default_open): - imgui.text("Tool Preset")""" -content = content.replace(old_agent_tools_start, new_agent_tools_start) - -# Wait, if I do collapsing header, I need to indent the rest of the function. -# Instead of indenting the whole function, I can just use the header. -# But wait, ImGui collapsing_header doesn't require indenting, it just returns true if open. -# So I should write it properly: -old_agent_tools_func = """ def _render_agent_tools_panel(self) -> None: - imgui.text_colored(C_LBL, 'Active Tool Preset') - presets = self.controller.tool_presets - preset_names = [""] + sorted(list(presets.keys())) - - # Gracefully handle None or missing preset - active = getattr(self, "ui_active_tool_preset", "") - if active is None: active = "" - try: - idx = preset_names.index(active) - except ValueError: - idx = 0 - - ch, new_idx = imgui.combo("##tool_preset_select", idx, preset_names) - if ch: - self.ui_active_tool_preset = preset_names[new_idx] - - imgui.same_line() - if imgui.button("Manage Presets##tools"): - self.show_tool_preset_manager_window = True - if imgui.is_item_hovered(): - imgui.set_tooltip("Configure tool availability and default modes.") - - imgui.dummy(imgui.ImVec2(0, 8)) - active_name = self.ui_active_tool_preset - if active_name and active_name in presets: - preset = presets[active_name] - for cat_name, tools in preset.categories.items(): - if imgui.tree_node(cat_name): - for tool in tools: - if tool.weight >= 5: - imgui.text_colored(vec4(255, 100, 100), "[HIGH]") - imgui.same_line() - elif tool.weight == 4: - imgui.text_colored(vec4(255, 255, 100), "[PREF]") - imgui.same_line() - elif tool.weight == 2: - imgui.text_colored(vec4(255, 150, 50), "[REJECT]") - imgui.same_line() - elif tool.weight <= 1: - imgui.text_colored(vec4(180, 180, 180), "[LOW]") - imgui.same_line() - - imgui.text(tool.name) - imgui.same_line(180) - - mode = tool.approval - if imgui.radio_button(f"Auto##{cat_name}_{tool.name}", mode == "auto"): - tool.approval = "auto" - imgui.same_line() - if imgui.radio_button(f"Ask##{cat_name}_{tool.name}", mode == "ask"): - tool.approval = "ask" - imgui.tree_pop()""" - -new_agent_tools_func = """ def _render_agent_tools_panel(self) -> None: - if imgui.collapsing_header("Active Tool Presets & Biases", imgui.TreeNodeFlags_.default_open): - imgui.text("Tool Preset") - presets = self.controller.tool_presets - preset_names = [""] + sorted(list(presets.keys())) - - # Gracefully handle None or missing preset - active = getattr(self, "ui_active_tool_preset", "") - if active is None: active = "" - try: - idx = preset_names.index(active) - except ValueError: - idx = 0 - - ch, new_idx = imgui.combo("##tool_preset_select", idx, preset_names) - if ch: - self.ui_active_tool_preset = preset_names[new_idx] - - imgui.same_line() - if imgui.button("Manage Tools##tools"): - self.show_tool_preset_manager_window = True - if imgui.is_item_hovered(): - imgui.set_tooltip("Configure tool availability and default modes.") - - imgui.dummy(imgui.ImVec2(0, 4)) -""" + "\n ".join(old_bias_block.split("\n")) + """ - - imgui.dummy(imgui.ImVec2(0, 8)) - active_name = self.ui_active_tool_preset - if active_name and active_name in presets: - preset = presets[active_name] - for cat_name, tools in preset.categories.items(): - if imgui.tree_node(cat_name): - for tool in tools: - if tool.weight >= 5: - imgui.text_colored(vec4(255, 100, 100), "[HIGH]") - imgui.same_line() - elif tool.weight == 4: - imgui.text_colored(vec4(255, 255, 100), "[PREF]") - imgui.same_line() - elif tool.weight == 2: - imgui.text_colored(vec4(255, 150, 50), "[REJECT]") - imgui.same_line() - elif tool.weight <= 1: - imgui.text_colored(vec4(180, 180, 180), "[LOW]") - imgui.same_line() - - imgui.text(tool.name) - imgui.same_line(180) - - mode = tool.approval - if imgui.radio_button(f"Auto##{cat_name}_{tool.name}", mode == "auto"): - tool.approval = "auto" - imgui.same_line() - if imgui.radio_button(f"Ask##{cat_name}_{tool.name}", mode == "ask"): - tool.approval = "ask" - imgui.tree_pop()""" -content = content.replace(old_agent_tools_func, new_agent_tools_func) - -# Fix cache text display in Usage Analytics -content = content.replace('self._gemini_cache_text = f"Gemini Caches: {count} ({size_bytes / 1024:.1f} KB)"', 'self._gemini_cache_text = f"Cache Usage: {count} ({size_bytes / 1024:.1f} KB)"') -content = content.replace('imgui.text_colored(C_LBL, f"Gemini Cache: ACTIVE | Age: {age:.0f}s / {ttl}s | Renews at: {ttl * 0.9:.0f}s")', 'imgui.text_colored(C_LBL, f"Cache Usage: ACTIVE | Age: {age:.0f}s / {ttl}s | Renews at: {ttl * 0.9:.0f}s")') -content = content.replace('imgui.text_disabled("Gemini Cache: INACTIVE")', 'imgui.text_disabled("Cache Usage: INACTIVE")') - -# Also, user requested: "The persona should problably just mess with the project system prompt for now." -# Currently in persona selection: `ai_client.system_instruction = persona.system_prompt` -# Let's change that to `self.ui_project_system_prompt = persona.system_prompt` and remove ai_client direct injection -content = content.replace('ai_client.system_instruction = persona.system_prompt', 'self.ui_project_system_prompt = persona.system_prompt') - -with open("src/gui_2.py", "w", encoding="utf-8") as f: - f.write(content) -print("done") diff --git a/scripts/refactor_ai_settings_3.py b/scripts/refactor_ai_settings_3.py deleted file mode 100644 index 0d6a2455..00000000 --- a/scripts/refactor_ai_settings_3.py +++ /dev/null @@ -1,228 +0,0 @@ -import sys - -with open("src/gui_2.py", "r", encoding="utf-8") as f: - content = f.read() - -# 1. Update _gui_func: -# Extract Persona out of Provider panel. I will create a new method _render_persona_selector_panel -old_gui_settings = """ if self.show_windows.get("AI Settings", False): - exp, opened = imgui.begin("AI Settings", self.show_windows["AI Settings"]) - self.show_windows["AI Settings"] = bool(opened) - if exp: - if imgui.collapsing_header("Provider & Model"): - self._render_provider_panel() - if imgui.collapsing_header("System Prompts"): - self._render_system_prompts_panel() - self._render_agent_tools_panel() - self._render_cache_panel() - - imgui.end() - if self.ui_separate_usage_analytics and self.show_windows.get("Usage Analytics", False): - exp, opened = imgui.begin("Usage Analytics", self.show_windows["Usage Analytics"]) - self.show_windows["Usage Analytics"] = bool(opened) - if exp: - self._render_usage_analytics_panel() - imgui.end()""" - -new_gui_settings = """ if self.show_windows.get("AI Settings", False): - exp, opened = imgui.begin("AI Settings", self.show_windows["AI Settings"]) - self.show_windows["AI Settings"] = bool(opened) - if exp: - self._render_persona_selector_panel() - if imgui.collapsing_header("Provider & Model"): - self._render_provider_panel() - if imgui.collapsing_header("System Prompts"): - self._render_system_prompts_panel() - self._render_agent_tools_panel() - - imgui.end() - if self.ui_separate_usage_analytics and self.show_windows.get("Usage Analytics", False): - exp, opened = imgui.begin("Usage Analytics", self.show_windows["Usage Analytics"]) - self.show_windows["Usage Analytics"] = bool(opened) - if exp: - self._render_usage_analytics_panel() - imgui.end()""" - -content = content.replace(old_gui_settings, new_gui_settings) - -# Update _render_usage_analytics_panel -old_usage = """ def _render_usage_analytics_panel(self) -> None: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_usage_analytics_panel") - self._render_token_budget_panel() - imgui.separator() - self._render_tool_analytics_panel() - imgui.separator() - self._render_session_insights_panel() - if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_usage_analytics_panel")""" - -new_usage = """ def _render_usage_analytics_panel(self) -> None: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_usage_analytics_panel") - self._render_token_budget_panel() - imgui.separator() - self._render_cache_panel() - imgui.separator() - self._render_tool_analytics_panel() - imgui.separator() - self._render_session_insights_panel() - if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_usage_analytics_panel")""" -content = content.replace(old_usage, new_usage) - -# Remove the persona block from _render_provider_panel and put it in _render_persona_selector_panel -old_persona_block = """ def _render_provider_panel(self) -> None: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") - imgui.text("Persona") - if not hasattr(self, 'ui_active_persona'): - self.ui_active_persona = "" - personas = getattr(self.controller, 'personas', {}) - if imgui.begin_combo("##persona", self.ui_active_persona or "None"): - if imgui.selectable("None", not self.ui_active_persona)[0]: - self.ui_active_persona = "" - for pname in sorted(personas.keys()): - if imgui.selectable(pname, pname == self.ui_active_persona)[0]: - self.ui_active_persona = pname - if pname in personas: - persona = personas[pname] - self._editing_persona_name = persona.name - self._editing_persona_provider = persona.provider or "" - self._editing_persona_model = persona.model or "" - self._editing_persona_system_prompt = persona.system_prompt or "" - self._editing_persona_temperature = persona.temperature or 0.7 - self._editing_persona_max_tokens = persona.max_output_tokens or 4096 - self._editing_persona_tool_preset_id = persona.tool_preset or "" - self._editing_persona_bias_profile_id = persona.bias_profile or "" - import json - self._editing_persona_preferred_models = json.dumps(persona.preferred_models) if persona.preferred_models else "[]" - self._editing_persona_is_new = False - if persona.provider and persona.provider in self.controller.PROVIDERS: - self.current_provider = persona.provider - if persona.model: - self.current_model = persona.model - if persona.temperature is not None: - ai_client.temperature = persona.temperature - if persona.max_output_tokens: - ai_client.max_output_tokens = persona.max_output_tokens - if persona.system_prompt: - self.ui_project_system_prompt = persona.system_prompt - if persona.tool_preset: - self.ui_active_tool_preset = persona.tool_preset - ai_client.set_tool_preset(persona.tool_preset) - if persona.bias_profile: - self.ui_active_bias_profile = persona.bias_profile - ai_client.set_bias_profile(persona.bias_profile) - imgui.end_combo() - imgui.same_line() - if imgui.button("Manage Personas"): - self.show_persona_editor_window = True - if self.ui_active_persona and self.ui_active_persona in personas: - persona = personas[self.ui_active_persona] - self._editing_persona_name = persona.name - self._editing_persona_provider = persona.provider or "" - self._editing_persona_model = persona.model or "" - self._editing_persona_system_prompt = persona.system_prompt or "" - self._editing_persona_temperature = persona.temperature if persona.temperature is not None else 0.7 - self._editing_persona_max_tokens = persona.max_output_tokens if persona.max_output_tokens is not None else 4096 - self._editing_persona_tool_preset_id = persona.tool_preset or "" - self._editing_persona_bias_profile_id = persona.bias_profile or "" - self._editing_persona_preferred_models_list = list(persona.preferred_models) if persona.preferred_models else [] - self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(persona.name) - self._editing_persona_is_new = False - else: - self._editing_persona_name = "" - self._editing_persona_provider = self.current_provider - self._editing_persona_model = self.current_model - self._editing_persona_system_prompt = "" - self._editing_persona_temperature = 0.7 - self._editing_persona_max_tokens = 4096 - self._editing_persona_tool_preset_id = "" - self._editing_persona_bias_profile_id = "" - self._editing_persona_preferred_models_list = [] - self._editing_persona_scope = "project" - self._editing_persona_is_new = True - imgui.separator() - imgui.text("Provider")""" - -new_persona_block = """ def _render_persona_selector_panel(self) -> None: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_persona_selector_panel") - imgui.text("Persona") - if not hasattr(self, 'ui_active_persona'): - self.ui_active_persona = "" - personas = getattr(self.controller, 'personas', {}) - if imgui.begin_combo("##persona", self.ui_active_persona or "None"): - if imgui.selectable("None", not self.ui_active_persona)[0]: - self.ui_active_persona = "" - for pname in sorted(personas.keys()): - if imgui.selectable(pname, pname == self.ui_active_persona)[0]: - self.ui_active_persona = pname - if pname in personas: - persona = personas[pname] - self._editing_persona_name = persona.name - self._editing_persona_system_prompt = persona.system_prompt or "" - self._editing_persona_tool_preset_id = persona.tool_preset or "" - self._editing_persona_bias_profile_id = persona.bias_profile or "" - import copy - self._editing_persona_preferred_models_list = copy.deepcopy(persona.preferred_models) if persona.preferred_models else [] - self._editing_persona_is_new = False - - # Apply persona to current state immediately - if persona.preferred_models and len(persona.preferred_models) > 0: - first_model = persona.preferred_models[0] - if first_model.get("provider"): - self.current_provider = first_model.get("provider") - if first_model.get("model"): - self.current_model = first_model.get("model") - if first_model.get("temperature") is not None: - ai_client.temperature = first_model.get("temperature") - self.temperature = first_model.get("temperature") - if first_model.get("max_output_tokens"): - ai_client.max_output_tokens = first_model.get("max_output_tokens") - self.max_tokens = first_model.get("max_output_tokens") - if first_model.get("history_trunc_limit"): - self.history_trunc_limit = first_model.get("history_trunc_limit") - - if persona.system_prompt: - self.ui_project_system_prompt = persona.system_prompt - if persona.tool_preset: - self.ui_active_tool_preset = persona.tool_preset - ai_client.set_tool_preset(persona.tool_preset) - if persona.bias_profile: - self.ui_active_bias_profile = persona.bias_profile - ai_client.set_bias_profile(persona.bias_profile) - imgui.end_combo() - imgui.same_line() - if imgui.button("Manage Personas"): - self.show_persona_editor_window = True - if self.ui_active_persona and self.ui_active_persona in personas: - persona = personas[self.ui_active_persona] - self._editing_persona_name = persona.name - self._editing_persona_system_prompt = persona.system_prompt or "" - self._editing_persona_tool_preset_id = persona.tool_preset or "" - self._editing_persona_bias_profile_id = persona.bias_profile or "" - import copy - self._editing_persona_preferred_models_list = copy.deepcopy(persona.preferred_models) if persona.preferred_models else [] - self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(persona.name) - self._editing_persona_is_new = False - else: - self._editing_persona_name = "" - self._editing_persona_system_prompt = "" - self._editing_persona_tool_preset_id = "" - self._editing_persona_bias_profile_id = "" - self._editing_persona_preferred_models_list = [{ - "provider": self.current_provider, - "model": self.current_model, - "temperature": getattr(self, "temperature", 0.7), - "max_output_tokens": getattr(self, "max_tokens", 4096), - "history_trunc_limit": getattr(self, "history_trunc_limit", 900000) - }] - self._editing_persona_scope = "project" - self._editing_persona_is_new = True - imgui.separator() - if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_persona_selector_panel") - - def _render_provider_panel(self) -> None: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") - imgui.text("Provider")""" -content = content.replace(old_persona_block, new_persona_block) - -with open("src/gui_2.py", "w", encoding="utf-8") as f: - f.write(content) -print("done gui updates") diff --git a/scripts/remove_bom.py b/scripts/remove_bom.py deleted file mode 100644 index 3e3047fb..00000000 --- a/scripts/remove_bom.py +++ /dev/null @@ -1,11 +0,0 @@ -import sys -with open('config.toml', 'rb') as f: - data = f.read() -BOM = bytes([0xef, 0xbb, 0xbf]) -if data.startswith(BOM): - with open('config.toml', 'wb') as f: - f.write(data[3:]) - print('BOM removed') -else: - print('No BOM found') -sys.exit(0) diff --git a/scripts/repair_scope.py b/scripts/repair_scope.py deleted file mode 100644 index 49a12419..00000000 --- a/scripts/repair_scope.py +++ /dev/null @@ -1,28 +0,0 @@ -from pathlib import Path -import re - -file_path = Path('src/app_controller.py') -lines = file_path.read_text(encoding='utf-8').splitlines() - -# We know the issue starts around line 1405 where `def cb_exit_prior_session(self):` is indented with 2 spaces. -# We will unindent everything that has 2 or more spaces back by 1 space, -# until we hit a line that is correctly 1-space indented (like `def start_services` or similar, if it exists). -# Actually, let's just use a state machine: find `def cb_exit_prior_session` and unindent everything until `def start_services` or end of file. - -in_bad_block = False -for i, line in enumerate(lines): - if re.match(r'^ def cb_exit_prior_session\(self\):', line): - in_bad_block = True - - if in_bad_block: - if line.startswith(' '): - lines[i] = line[1:] - elif line.startswith(' '): - pass # Keep it if it's already 1 space - - # Stop if we hit a properly indented class method - if in_bad_block and re.match(r'^ def start_services', line): - in_bad_block = False - -file_path.write_text('\n'.join(lines) + '\n', encoding='utf-8') -print("Scope repair complete.") diff --git a/scripts/temp_def.py b/scripts/temp_def.py deleted file mode 100644 index 35518fb4..00000000 --- a/scripts/temp_def.py +++ /dev/null @@ -1,97 +0,0 @@ -def format_code(source: str) -> str: - """ - Formats Python code to use exactly 1 space for indentation (including continuations), - max 1 blank line between top-level definitions, and 0 blank lines inside - function/method bodies. - - Args: - source: The Python source code to format. - - Returns: - The formatted source code. - """ - if not source: - return "" - tokens = list(tokenize.generate_tokens(io.StringIO(source).readline)) - lines = source.splitlines(keepends=True) - num_lines = len(lines) - block_level = 0 - paren_level = 0 - in_function_stack = [] - expecting_function_indent = False - line_indent = {} - line_is_blank = {i: True for i in range(1, num_lines + 2)} - line_is_string_interior = {i: False for i in range(1, num_lines + 2)} - line_seen = set() - pending_blank_lines = [] - for tok in tokens: - t_type = tok.type - t_string = tok.string - start_line, _ = tok.start - end_line, _ = tok.end - if t_type == tokenize.STRING: - for l in range(start_line + 1, end_line + 1): - line_is_string_interior[l] = True - if t_type not in (tokenize.NL, tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT, tokenize.ENDMARKER): - for l in range(start_line, end_line + 1): - line_is_blank[l] = False - pending_blank_lines = [] # Real content seen, clear pending blanks - # State updates that affect CURRENT line - if t_type == tokenize.INDENT: - block_level += 1 - if expecting_function_indent: - in_function_stack.append(block_level) - expecting_function_indent = False - elif t_type == tokenize.DEDENT: - block_level -= 1 - if in_function_stack and block_level < in_function_stack[-1]: - in_function_stack.pop() - # Retroactively update pending blank lines to the current (outer) level - for l in pending_blank_lines: - line_indent[l] = block_level + paren_level - if t_string in (')', ']', '}'): - paren_level -= 1 - if start_line not in line_seen: - line_indent[start_line] = block_level + paren_level - if t_type not in (tokenize.INDENT, tokenize.DEDENT): - line_seen.add(start_line) - if t_type in (tokenize.NL, tokenize.NEWLINE): - pending_blank_lines.append(start_line) - # State updates that affect FUTURE lines/tokens - if t_type == tokenize.NAME and t_string == 'def': - expecting_function_indent = True - if t_string in ('(', '[', '{'): - paren_level += 1 - output = [] - consecutive_blanks = 0 - for i in range(1, num_lines + 1): - if line_is_string_interior[i]: - output.append(lines[i-1]) - continue - if line_is_blank[i]: - indent = line_indent.get(i, 0) - if indent > 0: - continue - else: - if consecutive_blanks < 1: - output.append("\n") - consecutive_blanks += 1 - continue - original_line = lines[i-1] - indent = line_indent.get(i, 0) - stripped = original_line.lstrip() - # Enforce a 1-line gap before definitions/classes - is_def_start = stripped.startswith(('def ', 'class ', 'async def ', '@')) - if is_def_start and output and consecutive_blanks == 0: - prev_line = output[-1].strip() - # Don't add a gap if immediately following a block opener or another decorator - if prev_line and not prev_line.endswith(':') and not prev_line.startswith('@'): - output.append("\n") - consecutive_blanks += 1 - consecutive_blanks = 0 - output.append(" " * indent + stripped) - if not stripped.endswith('\n') and i < num_lines: - output[-1] += '\n' - if output and not output[-1].endswith('\n'): - output[-1] += '\n' - return "".join(output) diff --git a/scripts/temp_handle_test.py b/scripts/temp_handle_test.py deleted file mode 100644 index abb8062a..00000000 --- a/scripts/temp_handle_test.py +++ /dev/null @@ -1,12 +0,0 @@ -from imgui_bundle import hello_imgui, imgui - -def on_gui(): - imgui.text("Hello world") - -params = hello_imgui.RunnerParams() -params.app_window_params.borderless = True -params.app_window_params.borderless_movable = True -params.app_window_params.borderless_resizable = True -params.app_window_params.borderless_closable = True - -hello_imgui.run(params) diff --git a/scripts/test_font_config.py b/scripts/test_font_config.py deleted file mode 100644 index 665ea405..00000000 --- a/scripts/test_font_config.py +++ /dev/null @@ -1,12 +0,0 @@ - -from imgui_bundle import imgui, hello_imgui - -def test_font_config(): - config = imgui.ImFontConfig() - config.oversample_h = 3 - config.oversample_v = 3 - print(f"Oversample H: {config.oversample_h}") - print(f"Oversample V: {config.oversample_v}") - -if __name__ == "__main__": - test_font_config()