From f6c06ec38114e5c0bb7800fa401c55bf12e08f4f Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 21 Feb 2026 22:06:57 -0500 Subject: [PATCH] system prompt suspport --- MainContext.md | 5 +++-- ai_client.py | 16 ++++++++++++++-- config.toml | 3 ++- gui.py | 40 ++++++++++++++++++++++++++++++++++++++++ manual_slop.toml | 7 ++++++- project_manager.py | 2 +- 6 files changed, 66 insertions(+), 7 deletions(-) diff --git a/MainContext.md b/MainContext.md index 23a3845..1ebbc52 100644 --- a/MainContext.md +++ b/MainContext.md @@ -30,8 +30,8 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg - `file_cache.py` - stub; Anthropic Files API path removed; kept so stale imports don't break - `mcp_client.py` - MCP-style read-only file tools (read_file, list_directory, search_files, get_file_summary); allowlist enforced against project file_items + base_dirs; dispatched by ai_client tool-use loop for both Anthropic and Gemini - `summarize.py` - local heuristic summariser (no AI); .py via AST, .toml via regex, .md headings, generic preview; used by mcp_client.get_file_summary and aggregate.build_summary_section -- `config.toml` - global-only settings: [ai] provider+model, [theme] palette+font+scale, [projects] paths array + active path -- `manual_slop.toml` - per-project file: [project] name+git_dir, [output] namespace+output_dir, [files] base_dir+paths, [screenshots] base_dir+paths, [discussion] roles+active+[discussion.discussions.] git_commit+last_updated+history +- `config.toml` - global-only settings: [ai] provider+model+system_prompt, [theme] palette+font+scale, [projects] paths array + active path +- `manual_slop.toml` - per-project file: [project] name+git_dir+system_prompt, [output] namespace+output_dir, [files] base_dir+paths, [screenshots] base_dir+paths, [discussion] roles+active+[discussion.discussions.] git_commit+last_updated+history - `credentials.toml` - gemini api_key, anthropic api_key - `dpg_layout.ini` - Dear PyGui window layout file (auto-saved on exit, auto-loaded on startup); gitignore this per-user @@ -45,6 +45,7 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg - **Message** - multiline input, Gen+Send button, MD Only button, Reset session button, -> History button - **Response** - readonly multiline displaying last AI response, -> History button - **Tool Calls** - scrollable log of every PowerShell tool call the AI made; Clear button +- **System Prompts** - global (all projects) and project-specific multiline text areas for injecting custom system instructions. Combined with the built-in tool prompt. - **Comms History** - rich structured live log of every API interaction; status line at top; colour legend; Clear button **Layout persistence:** diff --git a/ai_client.py b/ai_client.py index 8c320f4..4d8a231 100644 --- a/ai_client.py +++ b/ai_client.py @@ -48,6 +48,18 @@ _SYSTEM_PROMPT = ( "need to re-read files that are already provided in the block." ) + +_custom_system_prompt: str = "" + +def set_custom_system_prompt(prompt: str): + global _custom_system_prompt + _custom_system_prompt = prompt + +def _get_combined_system_prompt() -> str: + if _custom_system_prompt.strip(): + return f"{_SYSTEM_PROMPT}\n\n[USER SYSTEM PROMPT]\n{_custom_system_prompt}" + return _SYSTEM_PROMPT + # ------------------------------------------------------------------ comms log _comms_log: list[dict] = [] @@ -403,7 +415,7 @@ def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: _gemini_chat = _gemini_client.chats.create( model=_model, config=types.GenerateContentConfig( - system_instruction=_SYSTEM_PROMPT, + system_instruction=_get_combined_system_prompt(), tools=[_gemini_tool_declaration()] ) ) @@ -635,7 +647,7 @@ def _send_anthropic(md_content: str, user_message: str, base_dir: str, file_item system=[ { "type": "text", - "text": _SYSTEM_PROMPT, + "text": _get_combined_system_prompt(), "cache_control": {"type": "ephemeral"}, } ], diff --git a/config.toml b/config.toml index 8f85a5e..7b3b0d1 100644 --- a/config.toml +++ b/config.toml @@ -1,6 +1,7 @@ [ai] provider = "gemini" -model = "gemini-3-flash-preview" +model = "gemini-3.1-pro-preview" +system_prompt = "DO NOT EVER make a shell script unless told to. DO NOT EVER make a readme or a file describing your changes unless your are told to. If you have commands I should be entering into the command line or if you have something to explain to me, please just use code blocks or normal text output. DO NOT DO ANYTHING OTHER THAN WHAT YOU WERE TOLD TODO. DO NOT EVER, EVER DO ANYTHING OTHER THAN WHAT YOU WERE TOLD TO DO. IF YOU WANT TO DO OTHER THINGS, SIMPLY SUGGEST THEM, AND THEN I WILL REVIEW YOUR CHANGES, AND MAKE THE DECISION ON HOW TO PROCEED. WHEN WRITING SCRIPTS USE A 120-160 character limit per line. I don't want to see scrunched code.\n" [theme] palette = "10x Dark" diff --git a/gui.py b/gui.py index 9cc4e1b..d11e677 100644 --- a/gui.py +++ b/gui.py @@ -465,6 +465,8 @@ class App: dpg.set_value("project_name_text", f"Active: {name}") if dpg.does_item_exist("project_git_dir"): dpg.set_value("project_git_dir", proj.get("project", {}).get("git_dir", "")) + if dpg.does_item_exist("project_system_prompt"): + dpg.set_value("project_system_prompt", proj.get("project", {}).get("system_prompt", "")) def _save_active_project(self): """Write self.project to the active project .toml file.""" @@ -688,6 +690,8 @@ class App: proj.setdefault("project", {}) if dpg.does_item_exist("project_git_dir"): proj["project"]["git_dir"] = dpg.get_value("project_git_dir") + if dpg.does_item_exist("project_system_prompt"): + proj["project"]["system_prompt"] = dpg.get_value("project_system_prompt") # Discussion self._flush_disc_entries_to_project() @@ -701,6 +705,8 @@ class App: "provider": self.current_provider, "model": self.current_model, } + if dpg.does_item_exist("global_system_prompt"): + self.config["ai"]["system_prompt"] = dpg.get_value("global_system_prompt") self.config["projects"] = { "paths": self.project_paths, "active": self.active_project_path, @@ -970,6 +976,13 @@ class App: user_msg = dpg.get_value("ai_input") base_dir = dpg.get_value("files_base_dir") + global_sp = dpg.get_value("global_system_prompt") if dpg.does_item_exist("global_system_prompt") else "" + project_sp = dpg.get_value("project_system_prompt") if dpg.does_item_exist("project_system_prompt") else "" + combined_sp = [] + if global_sp: combined_sp.append(global_sp.strip()) + if project_sp: combined_sp.append(project_sp.strip()) + ai_client.set_custom_system_prompt("\n\n".join(combined_sp)) + def do_send(): try: response = ai_client.send(self.last_md, user_msg, base_dir, self.last_file_items) @@ -1615,6 +1628,33 @@ class App: with dpg.child_window(tag="comms_scroll", height=-1, border=False, horizontal_scrollbar=True): pass + # ---- System Prompts panel ---- + with dpg.window( + label="System Prompts", + tag="win_system_prompts", + pos=(416, 804), + width=400, + height=300, + no_close=True, + ): + dpg.add_text("Global System Prompt (all projects)") + dpg.add_input_text( + tag="global_system_prompt", + default_value=self.config.get("ai", {}).get("system_prompt", ""), + multiline=True, + width=-1, + height=100, + ) + dpg.add_separator() + dpg.add_text("Project System Prompt") + dpg.add_input_text( + tag="project_system_prompt", + default_value=self.project.get("project", {}).get("system_prompt", ""), + multiline=True, + width=-1, + height=100, + ) + self._build_theme_window() def run(self): diff --git a/manual_slop.toml b/manual_slop.toml index 1d387d8..bd478c2 100644 --- a/manual_slop.toml +++ b/manual_slop.toml @@ -1,6 +1,7 @@ [project] name = "manual_slop" git_dir = "C:/projects/manual_slop" +system_prompt = "Make sure to update MainContext.md every time.\nMake destructive modifications to the project, ITS OK, I HAVE GIT HISTORY TO MANAGE THE PROJECTS.\n\nMainContext.md should be read if the discussion doesn't resolve whats being worked on." [output] namespace = "manual_slop" @@ -84,8 +85,12 @@ history = [ [discussion.discussions."Support for system prompt"] git_commit = "f258fc5765d647eb821716bce3d2000fb2ba2857" -last_updated = "2026-02-21T21:53:43" +last_updated = "2026-02-21T22:06:39" history = [ "@2026-02-21T21:52:16\nUser:\ngemini testing 123 you get this message, first time using you proper in this custom frontend.", "@2026-02-21T21:52:17\nAI:\nLoud and clear! I've received your message through your **Manual Slop** frontend. It looks like a very capable environment—I can see you've implemented:\n\n1. **Multi-provider support** (Anthropic and Gemini).\n2. **Tool use/MCP-like capabilities** (file reading, directory listing, searching, etc.).\n3. **Project & Discussion management** via TOML files.\n4. **Rich GUI** using `dearpygui`.\n\nSince this is our first \"proper\" session in this interface, I'm ready to help you develop, debug, or refine the project. I have access to your local files through the tools you've provided, so I can see the codebase and even run PowerShell scripts if needed.\n\nIs there a specific feature you'd like to work on next, or any bugs in the Gemini integration you've noticed during your \"123\" test?", + "@2026-02-21T21:59:34\nUser:\nYeah lets add the ability for the user to support system prompt templating from their side, I know the ai_client.py has some baked in so we can keep portion of it, I jsut want the suer to be able to inject project-agnostic and project specific system prompts.\nIf you think thats not a good idea let me know.", + "@2026-02-21T21:59:35\nAI:\n---\n\n\n\nYeah lets add the ability for the user to support system prompt templating from their side, I know the ai_client.py has some baked in so we can keep portion of it, I jsut want the suer to be able to inject project-agnostic and project specific system prompts.\nIf you think thats not a good idea let me know.", + "@2026-02-21T22:01:32\nUser:\nUm are you working correctly you stopped for some rason I'll send a screen cap of the comms history...", + "@2026-02-21T22:01:40\nAI:\n---\n\n\nI successfully applied the changes. Let me know if everything is working fine now.", ] diff --git a/project_manager.py b/project_manager.py index f47b4e0..4b464c2 100644 --- a/project_manager.py +++ b/project_manager.py @@ -90,7 +90,7 @@ def default_discussion() -> dict: def default_project(name: str = "unnamed") -> dict: return { - "project": {"name": name, "git_dir": ""}, + "project": {"name": name, "git_dir": "", "system_prompt": ""}, "output": {"namespace": name, "output_dir": "./md_gen"}, "files": {"base_dir": ".", "paths": []}, "screenshots": {"base_dir": ".", "paths": []},