Private
Public Access
reading more code, slight adjustment to ast structual file editor ux (radio buttons going off viewport)
This commit is contained in:
+8
-23
@@ -46,17 +46,12 @@ from src.warmup import WarmupManager
|
||||
|
||||
|
||||
def parse_symbols(text: str) -> list[str]:
|
||||
"""
|
||||
Finds all occurrences of '@SymbolName' in text and returns SymbolName.
|
||||
"""Finds all occurrences of '@SymbolName' in text and returns SymbolName.
|
||||
SymbolName can be a function, class, or method (e.g. @MyClass, @my_func, @MyClass.my_method).
|
||||
[C: tests/test_symbol_lookup.py:TestSymbolLookup.test_parse_symbols_basic, tests/test_symbol_lookup.py:TestSymbolLookup.test_parse_symbols_edge_cases, tests/test_symbol_lookup.py:TestSymbolLookup.test_parse_symbols_methods, tests/test_symbol_lookup.py:TestSymbolLookup.test_parse_symbols_mixed, tests/test_symbol_lookup.py:TestSymbolLookup.test_parse_symbols_no_symbols]
|
||||
"""
|
||||
return re.findall(r"@([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)", text)
|
||||
|
||||
def get_symbol_definition(symbol: str, files: list[str]) -> tuple[str, str, int] | None:
|
||||
"""
|
||||
[C: tests/test_symbol_lookup.py:TestSymbolLookup.test_get_symbol_definition_found, tests/test_symbol_lookup.py:TestSymbolLookup.test_get_symbol_definition_not_found]
|
||||
"""
|
||||
for file_path in files:
|
||||
result = mcp_client.py_get_symbol_info(file_path, symbol)
|
||||
if isinstance(result, tuple):
|
||||
@@ -66,9 +61,6 @@ def get_symbol_definition(symbol: str, files: list[str]) -> tuple[str, str, int]
|
||||
|
||||
class ConfirmDialog:
|
||||
def __init__(self, script: str, base_dir: str) -> None:
|
||||
"""
|
||||
[C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__]
|
||||
"""
|
||||
self._uid = str(uuid.uuid4())
|
||||
self._script = str(script) if script is not None else ""
|
||||
self._base_dir = str(base_dir) if base_dir is not None else ""
|
||||
@@ -1657,10 +1649,7 @@ class AppController:
|
||||
self._pending_gui_tasks.append({'action': 'set_tool_log_dirty'})
|
||||
|
||||
def _process_pending_gui_tasks(self) -> None:
|
||||
"""
|
||||
Processes pending GUI tasks from the queue on the main render thread.
|
||||
[C: src/gui_2.py:App._render_main_interface, tests/test_api_hook_extensions.py:test_app_processes_new_actions, tests/test_gui_updates.py:test_gui_updates_on_event, tests/test_live_gui_integration_v2.py:test_user_request_error_handling, tests/test_live_gui_integration_v2.py:test_user_request_integration_flow, tests/test_mma_orchestration_gui.py:test_handle_ai_response_fallback, tests/test_mma_orchestration_gui.py:test_handle_ai_response_with_stream_id, tests/test_mma_orchestration_gui.py:test_process_pending_gui_tasks_mma_spawn_approval, tests/test_mma_orchestration_gui.py:test_process_pending_gui_tasks_show_track_proposal, tests/test_process_pending_gui_tasks.py:test_gcli_path_updates_adapter, tests/test_process_pending_gui_tasks.py:test_process_pending_gui_tasks_drag, tests/test_process_pending_gui_tasks.py:test_process_pending_gui_tasks_right_click, tests/test_process_pending_gui_tasks.py:test_redundant_calls_in_process_pending_gui_tasks]
|
||||
"""
|
||||
"""Processes pending GUI tasks from the queue on the main render thread."""
|
||||
now = time.time()
|
||||
if hasattr(self, 'event_queue') and hasattr(self.event_queue, 'websocket_server') and self.event_queue.websocket_server:
|
||||
if now - self._last_telemetry_time >= 1.0:
|
||||
@@ -1836,25 +1825,21 @@ class AppController:
|
||||
mcp_p = Path(mcp_path)
|
||||
if not mcp_p.is_absolute() and self.active_project_path:
|
||||
mcp_p = Path(self.active_project_path).parent / mcp_path
|
||||
if mcp_p.exists():
|
||||
self.mcp_config = models.load_mcp_config(str(mcp_p))
|
||||
else:
|
||||
self.mcp_config = models.MCPConfiguration()
|
||||
if mcp_p.exists(): self.mcp_config = models.load_mcp_config(str(mcp_p))
|
||||
else: self.mcp_config = models.MCPConfiguration()
|
||||
else:
|
||||
self.mcp_config = models.MCPConfiguration()
|
||||
|
||||
rag_data = self.config.get('rag')
|
||||
if rag_data:
|
||||
self.rag_config = models.RAGConfig.from_dict(rag_data)
|
||||
else:
|
||||
self.rag_config = models.RAGConfig()
|
||||
if rag_data: self.rag_config = models.RAGConfig.from_dict(rag_data)
|
||||
else: self.rag_config = models.RAGConfig()
|
||||
|
||||
self.rag_engine = None
|
||||
if self.rag_config.enabled:
|
||||
self._sync_rag_engine()
|
||||
if self.rag_config.enabled: self._sync_rag_engine()
|
||||
|
||||
from src.personas import PersonaManager
|
||||
self.persona_manager = PersonaManager(Path(self.active_project_path).parent if self.active_project_path else None)
|
||||
|
||||
from src.vendor_capabilities import get_capabilities
|
||||
try:
|
||||
caps = get_capabilities(self.current_provider, self.current_model)
|
||||
|
||||
+42
-59
@@ -3579,13 +3579,11 @@ def render_context_composition_panel(app: App) -> None:
|
||||
render_context_screenshots(app)
|
||||
|
||||
def render_ast_inspector_modal(app: App) -> None:
|
||||
"""
|
||||
Renders the 'Structural File Editor' modal dialog.
|
||||
"""Renders the 'Structural File Editor' modal dialog.
|
||||
Provides an interactive tree-sitter AST inspector to mask classes, methods, or
|
||||
functions and extract custom annotated slices (Definition, Signature, Hide).
|
||||
|
||||
SSDL Shape:
|
||||
`[B:open_modal?] -> [Q:outline] -> [I:render_ast_tree]`
|
||||
SSDL: `[B:open_modal?] -> [Q:outline] -> [I:render_ast_tree]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+-------------------------------------------------------------+
|
||||
@@ -3629,7 +3627,7 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
outline = f"Error fetching outline: {e}"
|
||||
|
||||
app._cached_ast_nodes = []
|
||||
import re
|
||||
import re #TODO(Ed): Review local import
|
||||
pattern = re.compile(r'^(\s*)\[(.*?)\] (.*?) \(Lines (\d+)-(\d+)\)')
|
||||
stack = [] # (indent, name)
|
||||
for line in outline.splitlines():
|
||||
@@ -3671,11 +3669,18 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
|
||||
# --- LEFT COLUMN: AST Tree & Slice Management ---
|
||||
imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 0), True)
|
||||
if True:
|
||||
# if True:
|
||||
if imgui.collapsing_header("AST Tree", imgui.TreeNodeFlags_.default_open):
|
||||
if not getattr(app, '_cached_ast_nodes', None): imgui.text("No AST nodes found.")
|
||||
else:
|
||||
with imscope.table('ast tree members', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.sizing_stretch_prop)
|
||||
imgui.table_setup_column("symbol", imgui.TableColumnFlags_.width_fixed, 400)
|
||||
imgui.table_setup_column("option", imgui.TableColumnFlags_.width_stretch)
|
||||
imgui.table_next_row()
|
||||
imgui.table_next_column()
|
||||
for node in app._cached_ast_nodes:
|
||||
imgui.table_next_row()
|
||||
imgui.table_next_column()
|
||||
indent = node['indent']
|
||||
kind = node['kind']
|
||||
name = node['name']
|
||||
@@ -3687,12 +3692,14 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
|
||||
if imgui.is_item_hovered():
|
||||
app._hovered_ast_node = full_path
|
||||
imgui.table_next_column()
|
||||
|
||||
btn_width = 150
|
||||
avail_width = imgui.get_content_region_avail().x
|
||||
do_align = avail_width > btn_width if isinstance(avail_width, (int, float)) else False
|
||||
if do_align: imgui.same_line(imgui.get_window_width() - btn_width)
|
||||
else: imgui.same_line()
|
||||
# btn_width = 150
|
||||
# avail_width = imgui.get_content_region_avail().x
|
||||
# do_align = avail_width > btn_width if isinstance(avail_width, (int, float)) else False
|
||||
# if do_align: imgui.same_line((avail_width - btn_width))
|
||||
# else: imgui.same_line()
|
||||
# imgui.same_line((avail_width - btn_width) * 0.925)
|
||||
|
||||
if not hasattr(f_item, 'ast_mask'): f_item.ast_mask = {}
|
||||
current_mode = f_item.ast_mask.get(full_path, 'hide')
|
||||
@@ -6275,11 +6282,9 @@ def render_heavy_text(app: App, label: str, content: str, id_suffix: str = "") -
|
||||
#region: MMA
|
||||
|
||||
def render_mma_dashboard(app: App) -> None:
|
||||
"""
|
||||
Main MMA dashboard interface.
|
||||
"""Main MMA dashboard interface.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:focus_selector] -> [I:track_summary] -> [B:epic_planner] -> [I:track_browser] -> [B:global_controls] -> [I:usage_analytics] -> [I:ticket_queue] -> [I:task_dag] => [I:agent_streams]`
|
||||
SSDL: `[I:focus_selector] -> [I:track_summary] -> [B:epic_planner] -> [I:track_browser] -> [B:global_controls] -> [I:usage_analytics] -> [I:ticket_queue] -> [I:task_dag] => [I:agent_streams]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6325,13 +6330,11 @@ def render_mma_dashboard(app: App) -> None:
|
||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_mma_dashboard")
|
||||
|
||||
def render_mma_modals(app: App) -> None:
|
||||
"""
|
||||
Renders all MMA-specific approval and info modals: Tool Execution Approval,
|
||||
"""Renders all MMA-specific approval and info modals: Tool Execution Approval,
|
||||
MMA Step Approval (with optional payload edit), MMA Spawn Approval (with
|
||||
prompt/context editing), and the Cycle Detected error modal.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:pending_queues] => [I:tool_approval_modal] | [I:step_approval_modal] | [I:spawn_approval_modal] | [I:cycle_modal]`
|
||||
SSDL: `[I:pending_queues] => [I:tool_approval_modal] | [I:step_approval_modal] | [I:spawn_approval_modal] | [I:cycle_modal]`
|
||||
|
||||
ASCII Layout Map:
|
||||
Conditionally opens (at most one at a time):
|
||||
@@ -6426,13 +6429,11 @@ def render_mma_modals(app: App) -> None:
|
||||
imgui.end_popup()
|
||||
|
||||
def render_mma_track_summary(app: App) -> None:
|
||||
"""
|
||||
Renders the active-track summary row: track name, MMA pipeline status, and running
|
||||
"""Renders the active-track summary row: track name, MMA pipeline status, and running
|
||||
cost estimate, followed by a colour-coded progress bar and a 4-column breakdown table
|
||||
(Completed / In Progress / Blocked / Todo) and ETA estimation.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:track_name] -> [I:status_badge] -> [I:cost] -> [I:progress_bar] -> [I:stats_table] -> [I:eta]`
|
||||
SSDL: `[I:track_name] -> [I:status_badge] -> [I:cost] -> [I:progress_bar] -> [I:stats_table] -> [I:eta]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6470,11 +6471,9 @@ def render_mma_track_summary(app: App) -> None:
|
||||
imgui.text_colored(C_LBL(), "ETA:"); imgui.same_line(); imgui.text_colored(C_VAL(), f"~{int(eta_mins)}m ({remaining} tickets remaining)")
|
||||
|
||||
def render_mma_epic_planner(app: App) -> None:
|
||||
"""
|
||||
Renders the Epic Planning panel for Tier 1 strategy input and planning button.
|
||||
"""Renders the Epic Planning panel for Tier 1 strategy input and planning button.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:input_textbox] => [B:plan_button]`
|
||||
SSDL: `[I:input_textbox] => [B:plan_button]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6490,12 +6489,10 @@ def render_mma_epic_planner(app: App) -> None:
|
||||
if imgui.button('Plan Epic (Tier 1)', imgui.ImVec2(-1, 0)): app._cb_plan_epic()
|
||||
|
||||
def render_mma_conductor_setup(app: App) -> None:
|
||||
"""
|
||||
Renders the Conductor Setup panel. Runs a one-shot project-structure scan and
|
||||
"""Renders the Conductor Setup panel. Runs a one-shot project-structure scan and
|
||||
shows the summarised output in a read-only text area.
|
||||
|
||||
SSDL Shape:
|
||||
`[B:run_scan] => [I:summary_text]`
|
||||
SSDL: `[B:run_scan] => [I:summary_text]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6511,12 +6508,10 @@ def render_mma_conductor_setup(app: App) -> None:
|
||||
if app.ui_conductor_setup_summary: imgui.input_text_multiline("##setup_summary", app.ui_conductor_setup_summary, imgui.ImVec2(-1, 120), imgui.InputTextFlags_.read_only)
|
||||
|
||||
def render_mma_track_browser(app: App) -> None:
|
||||
"""
|
||||
Renders the Track Browser: a table listing all known tracks with status, progress bar,
|
||||
"""Renders the Track Browser: a table listing all known tracks with status, progress bar,
|
||||
and a [Load] button per row. Below the table is a form for creating a new track.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:tracks_table] -> [B:load_button] -> [I:create_track_form] => [B:create_track]`
|
||||
SSDL: `[I:tracks_table] -> [B:load_button] -> [I:create_track_form] => [B:create_track]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6560,13 +6555,11 @@ def render_mma_track_browser(app: App) -> None:
|
||||
app.ui_new_track_name = ""; app.ui_new_track_desc = ""
|
||||
|
||||
def render_mma_global_controls(app: App) -> None:
|
||||
"""
|
||||
Renders the MMA global controls bar: Step Mode (HITL) toggle, pipeline status label,
|
||||
"""Renders the MMA global controls bar: Step Mode (HITL) toggle, pipeline status label,
|
||||
Pause/Resume engine button, active tier badge, approval-pending blink indicator, and
|
||||
the Hot Reload shortcut.
|
||||
|
||||
SSDL Shape:
|
||||
`[B:step_mode] -> [I:status] -> [B:pause_resume] -> [I:active_tier] -> [I:approval_blink] -> [B:hot_reload]`
|
||||
SSDL: `[B:step_mode] -> [I:status] -> [B:pause_resume] -> [I:active_tier] -> [I:approval_blink] -> [B:hot_reload]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6604,13 +6597,11 @@ def render_mma_global_controls(app: App) -> None:
|
||||
imgui.same_line(); imgui.text_disabled("(Ctrl+Alt+R)")
|
||||
|
||||
def render_mma_usage_section(app: App) -> None:
|
||||
"""
|
||||
Renders the Tier Usage table (tokens and estimated cost per tier) and, when expanded,
|
||||
"""Renders the Tier Usage table (tokens and estimated cost per tier) and, when expanded,
|
||||
a collapsible Tier Model Config section with per-tier provider, model, tool-preset,
|
||||
and persona overrides.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:usage_table] -> [B:tier_model_config_header] => [I:combos_per_tier]`
|
||||
SSDL: `[I:usage_table] -> [B:tier_model_config_header] => [I:combos_per_tier]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6738,13 +6729,11 @@ def render_mma_agent_streams(app: App) -> None:
|
||||
imgui.end_tab_bar()
|
||||
|
||||
def render_tier_stream_panel(app: App, tier_key: str, stream_key: str | None) -> None:
|
||||
"""
|
||||
Renders a single tier's live streaming text panel. For Tier 1, 2, and 4 a single scrollable
|
||||
"""Renders a single tier's live streaming text panel. For Tier 1, 2, and 4 a single scrollable
|
||||
selectable text area is shown; for Tier 3 (stream_key=None), each worker ticket gets
|
||||
its own labelled, colour-coded sub-child with an auto-scroll behaviour.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:stream_text] => [I:single_scroll] | [I:worker_sub_children]`
|
||||
SSDL: `[I:stream_text] => [I:single_scroll] | [I:worker_sub_children]`
|
||||
|
||||
ASCII Layout Map (single-stream, e.g. Tier 1):
|
||||
+---------------------------------------------------------+
|
||||
@@ -6813,13 +6802,11 @@ def render_tier_stream_panel(app: App, tier_key: str, stream_key: str | None) ->
|
||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_tier_stream_panel")
|
||||
|
||||
def render_track_proposal_modal(app: App) -> None:
|
||||
"""
|
||||
Renders the Track Proposal modal. Shows Tier 1's generated implementation tracks
|
||||
"""Renders the Track Proposal modal. Shows Tier 1's generated implementation tracks
|
||||
with editable title and goal fields, and buttons to remove, start individual tracks,
|
||||
accept all, or cancel.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:proposed_tracks] -> [B:edit_title/goal] -> [B:remove/start] => [B:accept_all | B:cancel]`
|
||||
SSDL: `[I:proposed_tracks] -> [B:edit_title/goal] -> [B:remove/start] => [B:accept_all | B:cancel]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -6880,13 +6867,11 @@ def render_track_proposal_modal(app: App) -> None:
|
||||
imgui.end_popup()
|
||||
|
||||
def render_ticket_queue(app: App) -> None:
|
||||
"""
|
||||
Renders the Ticket Queue Management panel. Provides select-all/none controls,
|
||||
"""Renders the Ticket Queue Management panel. Provides select-all/none controls,
|
||||
bulk action buttons, a 7-column scrollable table of tickets with drag-to-reorder,
|
||||
priority/model combos, status labels, and per-row Kill/Block/Unblock actions.
|
||||
|
||||
SSDL Shape:
|
||||
`[B:select_all/none] -> [B:bulk_actions] -> [I:ticket_table] => [I:ticket_editor?]`
|
||||
SSDL: `[B:select_all/none] -> [B:bulk_actions] -> [I:ticket_table] => [I:ticket_editor?]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
@@ -7013,12 +6998,10 @@ def render_ticket_queue(app: App) -> None:
|
||||
imgui.end_table()
|
||||
|
||||
def render_task_dag_panel(app: App) -> None: # 4. Task DAG Visualizer
|
||||
"""
|
||||
Renders the interactive node editor DAG visualizer, mapping ticket relationships
|
||||
"""Renders the interactive node editor DAG visualizer, mapping ticket relationships
|
||||
and allowing creation or deletion of links.
|
||||
|
||||
SSDL Shape:
|
||||
`[I:task_nodes] -> [B:node_editor_canvas] => [I:link_connections]`
|
||||
SSDL: `[I:task_nodes] -> [B:node_editor_canvas] => [I:link_connections]`
|
||||
|
||||
ASCII Layout Map:
|
||||
+---------------------------------------------------------+
|
||||
|
||||
Reference in New Issue
Block a user