wip fixing regressions, removing hardcoded paths

This commit is contained in:
2026-03-06 19:24:08 -05:00
parent cb1440d61c
commit f439b5c525
5 changed files with 43 additions and 53 deletions

View File

@@ -32,10 +32,6 @@ from src import conductor_tech_lead
from src import multi_agent_conductor from src import multi_agent_conductor
from src import theme from src import theme
def save_config(config: dict[str, Any]) -> None:
with open(models.CONFIG_PATH, "wb") as f:
tomli_w.dump(config, f)
def hide_tk_root() -> Tk: def hide_tk_root() -> Tk:
root = Tk() root = Tk()
root.withdraw() root.withdraw()
@@ -1298,7 +1294,7 @@ class AppController:
self._flush_to_project() self._flush_to_project()
self._save_active_project() self._save_active_project()
self._flush_to_config() self._flush_to_config()
save_config(self.config) models.save_config(self.config)
self._set_status("config saved") self._set_status("config saved")
def _cb_disc_create(self) -> None: def _cb_disc_create(self) -> None:
@@ -1696,7 +1692,7 @@ class AppController:
self._flush_to_project() self._flush_to_project()
self._save_active_project() self._save_active_project()
self._flush_to_config() self._flush_to_config()
save_config(self.config) models.save_config(self.config)
track_id = self.active_track.id if self.active_track else None track_id = self.active_track.id if self.active_track else None
flat = project_manager.flat_config(self.project, self.active_discussion, track_id=track_id) flat = project_manager.flat_config(self.project, self.active_discussion, track_id=track_id)
full_md, path, file_items = aggregate.run(flat) full_md, path, file_items = aggregate.run(flat)
@@ -1720,8 +1716,9 @@ class AppController:
sys.stderr.write(f"[DEBUG] History summary length: {len(history)}\n") sys.stderr.write(f"[DEBUG] History summary length: {len(history)}\n")
sys.stderr.flush() sys.stderr.flush()
proj = project_manager.load_project(self.active_project_path) proj = project_manager.load_project(self.active_project_path)
flat = project_manager.flat_config(proj) flat = project_manager.flat_config(self.project)
file_items = aggregate.build_file_items(Path("."), flat.get("files", {}).get("paths", [])) file_items = aggregate.build_file_items(Path(self.ui_files_base_dir), flat.get("files", {}).get("paths", []))
_t1_baseline = len(ai_client.get_comms_log()) _t1_baseline = len(ai_client.get_comms_log())
tracks = orchestrator_pm.generate_tracks(self.ui_epic_input, flat, file_items, history_summary=history) tracks = orchestrator_pm.generate_tracks(self.ui_epic_input, flat, file_items, history_summary=history)
_t1_new = ai_client.get_comms_log()[_t1_baseline:] _t1_new = ai_client.get_comms_log()[_t1_baseline:]

View File

@@ -28,10 +28,6 @@ from imgui_bundle import imgui, hello_imgui, immapp, imgui_node_editor as ed
PROVIDERS: list[str] = ["gemini", "anthropic", "gemini_cli", "deepseek"] PROVIDERS: list[str] = ["gemini", "anthropic", "gemini_cli", "deepseek"]
COMMS_CLAMP_CHARS: int = 300 COMMS_CLAMP_CHARS: int = 300
def save_config(config: dict[str, Any]) -> None:
with open(models.CONFIG_PATH, "wb") as f:
tomli_w.dump(config, f)
def hide_tk_root() -> Tk: def hide_tk_root() -> Tk:
root = Tk() root = Tk()
root.withdraw() root.withdraw()
@@ -208,7 +204,7 @@ class App:
self._flush_to_project() self._flush_to_project()
self._save_active_project() self._save_active_project()
self._flush_to_config() self._flush_to_config()
save_config(self.config) models.save_config(self.config)
self.ai_status = "config saved" self.ai_status = "config saved"
if imgui.menu_item("Reset Session", "", False)[0]: if imgui.menu_item("Reset Session", "", False)[0]:
ai_client.reset_session() ai_client.reset_session()
@@ -248,7 +244,7 @@ class App:
self._flush_to_project() self._flush_to_project()
self._save_active_project() self._save_active_project()
self._flush_to_config() self._flush_to_config()
save_config(self.config) models.save_config(self.config)
except Exception: except Exception:
pass # silent — don't disrupt the GUI loop pass # silent — don't disrupt the GUI loop
# Sync pending comms # Sync pending comms
@@ -721,7 +717,7 @@ class App:
self._flush_to_project() self._flush_to_project()
self._save_active_project() self._save_active_project()
self._flush_to_config() self._flush_to_config()
save_config(self.config) models.save_config(self.config)
self.ai_status = "config saved" self.ai_status = "config saved"
ch, self.ui_word_wrap = imgui.checkbox("Word-Wrap (Read-only panels)", self.ui_word_wrap) ch, self.ui_word_wrap = imgui.checkbox("Word-Wrap (Read-only panels)", self.ui_word_wrap)
ch, self.ui_summary_only = imgui.checkbox("Summary Only (send file structure, not full content)", self.ui_summary_only) ch, self.ui_summary_only = imgui.checkbox("Summary Only (send file structure, not full content)", self.ui_summary_only)
@@ -1019,7 +1015,7 @@ class App:
self._flush_to_project() self._flush_to_project()
self._save_active_project() self._save_active_project()
self._flush_to_config() self._flush_to_config()
save_config(self.config) models.save_config(self.config)
self.ai_status = "discussion saved" self.ai_status = "discussion saved"
ch, self.ui_auto_add_history = imgui.checkbox("Auto-add message & response to history", self.ui_auto_add_history) ch, self.ui_auto_add_history = imgui.checkbox("Auto-add message & response to history", self.ui_auto_add_history)
# Truncation controls # Truncation controls
@@ -1994,7 +1990,7 @@ class App:
imgui.same_line() imgui.same_line()
if imgui.button("Apply Font (Requires Restart)"): if imgui.button("Apply Font (Requires Restart)"):
self._flush_to_config() self._flush_to_config()
save_config(self.config) models.save_config(self.config)
self.ai_status = "Font settings saved. Restart required." self.ai_status = "Font settings saved. Restart required."
imgui.separator() imgui.separator()
imgui.text("UI Scale (DPI)") imgui.text("UI Scale (DPI)")

View File

@@ -105,14 +105,24 @@ def _is_allowed(path: Path) -> bool:
CRITICAL: Blacklisted files (history) are NEVER allowed. CRITICAL: Blacklisted files (history) are NEVER allowed.
""" """
# Blacklist check from src.paths import get_config_path
name = path.name.lower() from src.ai_client import get_credentials_path
if name in ("history.toml", "config.toml", "credentials.toml") or name.endswith("_history.toml"):
return False
try: try:
rp = path.resolve(strict=True) rp = path.resolve(strict=True)
except (OSError, ValueError): except (OSError, ValueError):
rp = path.resolve() rp = path.resolve()
# Blacklist check by resolved path
if rp == get_config_path().resolve():
return False
if rp == get_credentials_path().resolve():
return False
name = path.name.lower()
if name == "history.toml" or name.endswith("_history.toml"):
return False
if rp in _allowed_paths: if rp in _allowed_paths:
return True return True
# Allow current working directory and subpaths by default if no base_dirs # Allow current working directory and subpaths by default if no base_dirs

View File

@@ -1,16 +1,21 @@
from __future__ import annotations from __future__ import annotations
import tomllib import tomllib
import os
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import List, Optional, Dict, Any, Union from typing import List, Optional, Dict, Any, Union
from pathlib import Path from pathlib import Path
from src.paths import get_config_path
CONFIG_PATH = Path(os.environ.get("SLOP_CONFIG", "config.toml")) CONFIG_PATH = get_config_path()
def load_config() -> dict[str, Any]: def load_config() -> dict[str, Any]:
with open(CONFIG_PATH, "rb") as f: with open(CONFIG_PATH, "rb") as f:
return tomllib.load(f) return tomllib.load(f)
def save_config(config: dict[str, Any]) -> None:
import tomli_w
with open(CONFIG_PATH, "wb") as f:
tomli_w.dump(config, f)
# Global constants for agent tools # Global constants for agent tools
AGENT_TOOL_NAMES = [ AGENT_TOOL_NAMES = [
"read_file", "read_file",
@@ -32,29 +37,6 @@ AGENT_TOOL_NAMES = [
"py_get_hierarchy" "py_get_hierarchy"
] ]
def parse_history_entries(history_strings: list[str], roles: list[str]) -> list[dict[str, Any]]:
"""Parse stored history strings back to disc entry dicts."""
import re
entries = []
for raw in history_strings:
ts = ""
rest = raw
if rest.startswith("@"):
nl = rest.find("\n")
if nl != -1:
ts = rest[1:nl]
rest = rest[nl + 1:]
known = roles or ["User", "AI"]
role_pat = re.compile(r"^(" + "|".join(re.escape(r) for r in known) + r"):", re.IGNORECASE)
match = role_pat.match(rest)
role = match.group(1) if match else "User"
if match:
content = rest[match.end():].strip()
else:
content = rest
entries.append({"role": role, "content": content, "collapsed": False, "ts": ts})
return entries
@dataclass @dataclass
class Ticket: class Ticket:
""" """

View File

@@ -113,10 +113,15 @@ def generate_tracks(user_request: str, project_config: dict[str, Any], file_item
if __name__ == "__main__": if __name__ == "__main__":
# Quick CLI test # Quick CLI test
import project_manager import project_manager
proj = project_manager.load_project("manual_slop.toml") from src import aggregate
flat = project_manager.flat_config(proj) test_project = Path("manual_slop.toml")
file_items = aggregate.build_file_items(Path("."), flat.get("files", {}).get("paths", [])) if not test_project.exists():
print("Testing Tier 1 Track Generation...") print(f"Error: {test_project} not found for testing.")
history = get_track_history_summary() else:
tracks = generate_tracks("Implement a basic unit test for the ai_client.py module.", flat, file_items, history_summary=history) proj = project_manager.load_project(str(test_project))
print(json.dumps(tracks, indent=2)) flat = project_manager.flat_config(proj)
file_items = aggregate.build_file_items(Path("."), flat.get("files", {}).get("paths", []))
print("Testing Tier 1 Track Generation...")
history = get_track_history_summary()
tracks = generate_tracks("Implement a basic unit test for the ai_client.py module.", flat, file_items, history_summary=history)
print(json.dumps(tracks, indent=2))