socratic-debug 0.0.4__tar.gz → 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {socratic_debug-0.0.4/socratic_debug.egg-info → socratic_debug-0.0.5}/PKG-INFO +40 -16
  2. socratic_debug-0.0.5/README.md +150 -0
  3. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/pyproject.toml +1 -1
  4. {socratic_debug-0.0.4 → socratic_debug-0.0.5/socratic_debug.egg-info}/PKG-INFO +40 -16
  5. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/socratic_debug.egg-info/SOURCES.txt +6 -2
  6. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/llm/factory.py +2 -1
  7. socratic_debug-0.0.5/src/agent/llm/invoker.py +28 -0
  8. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/llm/providers/ollama.py +1 -1
  9. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/nodes/diagnose_node.py +2 -2
  10. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/nodes/evaluate_node.py +2 -2
  11. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/nodes/questioner_node.py +7 -4
  12. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/nodes/solution_node.py +7 -4
  13. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/state/state.py +1 -1
  14. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/cli.py +1 -1
  15. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/events.py +20 -0
  16. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/hook.py +1 -1
  17. {socratic_debug-0.0.4/src → socratic_debug-0.0.5/src/utils}/config_creator.py +2 -2
  18. socratic_debug-0.0.5/src/utils/config_manager.py +45 -0
  19. socratic_debug-0.0.5/src/utils/config_watcher.py +22 -0
  20. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/utils/read_yaml.py +1 -1
  21. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/adapter.py +1 -0
  22. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/app.py +83 -1
  23. socratic_debug-0.0.5/ui/settings_drawer.py +277 -0
  24. socratic_debug-0.0.5/ui/styles.py +147 -0
  25. socratic_debug-0.0.5/ui/translations.py +77 -0
  26. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/views.py +12 -0
  27. socratic_debug-0.0.4/README.md +0 -126
  28. socratic_debug-0.0.4/ui/styles.py +0 -63
  29. socratic_debug-0.0.4/ui/translations.py +0 -37
  30. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/LICENSE +0 -0
  31. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/setup.cfg +0 -0
  32. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/socratic.py +0 -0
  33. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/socratic_debug.egg-info/dependency_links.txt +0 -0
  34. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/socratic_debug.egg-info/entry_points.txt +0 -0
  35. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/socratic_debug.egg-info/requires.txt +0 -0
  36. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/socratic_debug.egg-info/top_level.txt +0 -0
  37. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/__init__.py +0 -0
  38. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/graph/graph.py +0 -0
  39. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/llm/providers/__init__.py +0 -0
  40. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/llm/providers/openrouter.py +0 -0
  41. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/nodes/human_input_node.py +0 -0
  42. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/prompts/diagnose_prompt.py +0 -0
  43. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/prompts/evaluation_prompt.py +0 -0
  44. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/prompts/mentor_prompt.py +0 -0
  45. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/prompts/questioner_prompt.py +0 -0
  46. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/prompts/solution_prompt.py +0 -0
  47. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/agent/runner.py +0 -0
  48. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/extractor.py +0 -0
  49. {socratic_debug-0.0.4/src → socratic_debug-0.0.5/src/utils}/config_template.py +0 -0
  50. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/src/watcher.py +0 -0
  51. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/test/test_hook.py +0 -0
  52. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/__init__.py +0 -0
  53. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/bidi.py +0 -0
  54. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/console.py +0 -0
  55. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/templates.py +0 -0
  56. {socratic_debug-0.0.4 → socratic_debug-0.0.5}/ui/window.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: socratic-debug
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: Autonomous pedagogical debugging mentor powered by LangGraph, Rich, and LangSmith
5
5
  Author: Mohamed Elawakey
6
6
  Requires-Python: >=3.10
@@ -18,33 +18,55 @@ Dynamic: license-file
18
18
  # 🧠 Socratic Debug (`socratic`)
19
19
 
20
20
  > **Stop copying stack traces. Start mastering your bugs.**
21
- > An autonomous pedagogical debugger and mentor powered by LangGraph, PyQt6, and LangSmith.
21
+ > An autonomous pedagogical debugger and AI mentor built for **students learning to code** and **developers** who want to truly understand their errors instead of copy-pasting AI patches.
22
22
 
23
23
  [![CI](https://github.com/mohamedelawakey/socratic/actions/workflows/ci.yml/badge.svg)](https://github.com/mohamedelawakey/socratic/actions/workflows/ci.yml)
24
24
  [![PyPI version](https://img.shields.io/pypi/v/socratic-debug.svg?color=blue)](https://pypi.org/project/socratic-debug/)
25
- [![Python Version](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/)
26
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
25
+ [![Python Version](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://www.python.org/)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
27
+ [![LangChain](https://img.shields.io/badge/LangChain-1.4+-1C3C3C?logo=chainlink&logoColor=white)](https://www.langchain.com/)
28
+ [![LangGraph](https://img.shields.io/badge/LangGraph-1.2+-FF8800?logo=diagram-next&logoColor=white)](https://langchain-ai.github.io/langgraph/)
29
+ [![PyQt6](https://img.shields.io/badge/PyQt6-GUI%20Terminal-41CD52?logo=qt&logoColor=white)](https://riverbankcomputing.com/software/pyqt/)
30
+ [![Rich](https://img.shields.io/badge/Rich-Terminal%20UX-blueviolet)](https://github.com/Textualize/rich)
31
+
32
+ [📦 PyPI Package](https://pypi.org/project/socratic-debug/) • [🐛 Report Bug](https://github.com/mohamedelawakey/socratic/issues)
33
+
34
+ ---
35
+
36
+ <p align="center">
37
+ <a href="test/test_hook.py">
38
+ <img src="assets/socratic_ui_demo.png" alt="Socratic Debug Interactive Desktop UI" width="900" style="border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.5);" />
39
+ </a>
40
+ <br />
41
+ <sub>⚡ <em>Interactive debugging session generated live from <a href="test/test_hook.py"><code>test/test_hook.py</code></a></em></sub>
42
+ </p>
27
43
 
28
44
  ---
29
45
 
30
46
  ## 💡 Why Socratic?
31
47
 
32
- When a runtime crash happens, most developers find themselves trapped in one of two extremes:
33
- 1. **The Intimidating Traceback:** Staring at a terrifying wall of 50-line red terminal text, unsure which line actually caused the root flaw.
34
- 2. **The "Copier" Reflex:** Blindly copying the error into an LLM chat, pasting the patch without understanding *why* it failed, only to trigger the exact same design mistake minutes later.
48
+ When a runtime crash happens, both beginners learning to program and seasoned developers often hit a wall:
49
+ 1. **For Students & Beginners:** A 50-line red terminal traceback feels overwhelming and cryptic. In the age of AI, copying the error into an LLM and pasting the generated code creates an illusion of progress—the student passes the assignment but never builds problem-solving intuition or mental models.
50
+ 2. **For Developers & Engineers:** Blindly pasting fixes without dissecting the failure mechanism leads to fragile code, cascading bugs, and recurring design flaws.
35
51
 
36
- **Socratic Debug changes the game.**
37
- Instead of dumping stack traces or spoon-feeding copy-paste patches, `socratic` intercepts uncaught runtime crashes and launches a **dedicated desktop mentorship window**. It analyzes the bug silently and guides you through a calibrated, interactive dialogue to help you **discover, understand, and fix the root cause yourself.**
52
+ **Socratic Debug changes the paradigm.**
53
+ Instead of dumping walls of red text or spoon-feeding copy-paste solutions, `socratic` intercepts uncaught runtime crashes and launches a **dedicated desktop mentorship window**. Powered by LangGraph, it acts like a personal coding instructor sitting right next to you:
54
+ - It guides you through a progressive, calibrated Socratic dialogue.
55
+ - It asks probing questions that help you spot the exact misconception on your own.
56
+ - It verifies your understanding before finally unlocking defensive programming best practices.
38
57
 
39
58
  ---
40
59
 
41
60
  ## ✨ Features
42
61
 
43
- - 🖥️ **Standalone Desktop Window:** Launches an isolated, dark-themed GUI terminal window right at the center of your screen. No terminal pollution.
62
+ - 🖥️ **Standalone Desktop Window:** Launches an isolated, dark-themed GUI terminal window right at the center of your screen. No terminal clutter.
63
+ - ⚙️ **In-App Settings Drawer & Secret Masking:** Configure models and API keys directly from the GUI with a slide-in settings panel, toggleable secret masking (`👁️`), and instant hot-reloading.
64
+ - ⚡ **Real-Time Auto-Reload & Live Watcher:** Background file monitor (`FileMonitor`) listens for fixes as you edit your code. It handles editor auto-save with a smart typing debounce, validates syntax, and auto-detects solutions live—no manual re-runs needed!
44
65
  - 🌍 **Pure Native BiDi & Arabic Support:** Flawlessly displays English and Arabic with full Right-to-Left (RTL) text shaping and formatting.
45
66
  - 🎯 **Calibrated Socratic Mentorship:** 3-tier adaptive hints (Observation ➔ Mechanism ➔ Idiomatic Prevention).
46
67
  - 🧠 **Smart Evaluator:** Distinguishes between partial observations (e.g., stating a variable's value) and true comprehension before unlocking the defensive code solution.
47
68
  - 🔌 **Universal LLM Support:** Plug into local models via **Ollama** (Gemma, Llama, Qwen) or cloud providers via **OpenRouter** / **Google Gemini**.
69
+ - 🏗️ **Clean Decoupled Architecture:** Core agent nodes and exception hooks communicate via an abstract `EventBus`, allowing Socratic to plug cleanly into Desktop GUI, CLI, or future IDE plugins (VS Code, JetBrains).
48
70
  - 📊 **Built-in Observability:** Native tracing with **LangSmith** to monitor latency, tokens, and node execution graphs.
49
71
  - 🌐 **Cross-Platform:** Runs seamlessly on **Linux**, **macOS**, and **Windows**.
50
72
 
@@ -87,6 +109,7 @@ socratic run my_script.py
87
109
  ```
88
110
  - If your script runs successfully, it outputs normally.
89
111
  - If an unhandled exception occurs, the **Socratic Mentor Window** springs to life immediately!
112
+ - Edit your file in your editor (VS Code, PyCharm, etc.)—Socratic will detect your fix live and celebrate your solution!
90
113
 
91
114
  ### Method 2: In-Process Runtime Hook
92
115
  If you are building an application or library and want Socratic guidance baked directly into development runs:
@@ -105,7 +128,7 @@ print(number_1 / number_2) # <-- ZeroDivisionError triggers Socratic window!
105
128
 
106
129
  ## ⚙️ Configuration (`.socratic.yaml`)
107
130
 
108
- When you run `socratic` for the first time, it automatically creates a `.socratic.yaml` config file in your project or home directory:
131
+ You can configure settings via the in-app **⚙️ Settings** drawer or directly in `.socratic.yaml`:
109
132
 
110
133
  ```yaml
111
134
  # LLM Provider: "ollama" or "openrouter"
@@ -117,7 +140,7 @@ provider_link: "http://localhost:11434"
117
140
  api_key: "your_api_key_here"
118
141
 
119
142
  # Mentor Personality & Language ("Arabic" or "English")
120
- socratic_language: "Arabic"
143
+ socratic_language: "English"
121
144
  socratic_style: "friendly"
122
145
 
123
146
  # Observability with LangSmith (Optional)
@@ -129,10 +152,11 @@ LANGSMITH_PROJECT: "socratic-debug"
129
152
  ---
130
153
 
131
154
  ## 🤝 Contributing
132
-
133
- We welcome contributions! Please review our [CONTRIBUTING.md](CONTRIBUTING.md) guidelines:
134
- - For large architectural changes or new features, **please open a GitHub Discussion first**.
135
- - For minor bug fixes, direct Pull Requests are warmly welcome.
155
+
156
+ We welcome contributions from developers worldwide! Please review our [CONTRIBUTING.md](CONTRIBUTING.md) guidelines:
157
+ - For feature requests or major changes, **please open a GitHub Discussion or Issue first**.
158
+ - For bug fixes, direct Pull Requests are warmly welcome.
159
+ - Browse our open issues labeled `good first issue` to start contributing.
136
160
 
137
161
  Please note that this project adheres to the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
138
162
 
@@ -0,0 +1,150 @@
1
+ # 🧠 Socratic Debug (`socratic`)
2
+
3
+ > **Stop copying stack traces. Start mastering your bugs.**
4
+ > An autonomous pedagogical debugger and AI mentor built for **students learning to code** and **developers** who want to truly understand their errors instead of copy-pasting AI patches.
5
+
6
+ [![CI](https://github.com/mohamedelawakey/socratic/actions/workflows/ci.yml/badge.svg)](https://github.com/mohamedelawakey/socratic/actions/workflows/ci.yml)
7
+ [![PyPI version](https://img.shields.io/pypi/v/socratic-debug.svg?color=blue)](https://pypi.org/project/socratic-debug/)
8
+ [![Python Version](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://www.python.org/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
10
+ [![LangChain](https://img.shields.io/badge/LangChain-1.4+-1C3C3C?logo=chainlink&logoColor=white)](https://www.langchain.com/)
11
+ [![LangGraph](https://img.shields.io/badge/LangGraph-1.2+-FF8800?logo=diagram-next&logoColor=white)](https://langchain-ai.github.io/langgraph/)
12
+ [![PyQt6](https://img.shields.io/badge/PyQt6-GUI%20Terminal-41CD52?logo=qt&logoColor=white)](https://riverbankcomputing.com/software/pyqt/)
13
+ [![Rich](https://img.shields.io/badge/Rich-Terminal%20UX-blueviolet)](https://github.com/Textualize/rich)
14
+
15
+ [📦 PyPI Package](https://pypi.org/project/socratic-debug/) • [🐛 Report Bug](https://github.com/mohamedelawakey/socratic/issues)
16
+
17
+ ---
18
+
19
+ <p align="center">
20
+ <a href="test/test_hook.py">
21
+ <img src="assets/socratic_ui_demo.png" alt="Socratic Debug Interactive Desktop UI" width="900" style="border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.5);" />
22
+ </a>
23
+ <br />
24
+ <sub>⚡ <em>Interactive debugging session generated live from <a href="test/test_hook.py"><code>test/test_hook.py</code></a></em></sub>
25
+ </p>
26
+
27
+ ---
28
+
29
+ ## 💡 Why Socratic?
30
+
31
+ When a runtime crash happens, both beginners learning to program and seasoned developers often hit a wall:
32
+ 1. **For Students & Beginners:** A 50-line red terminal traceback feels overwhelming and cryptic. In the age of AI, copying the error into an LLM and pasting the generated code creates an illusion of progress—the student passes the assignment but never builds problem-solving intuition or mental models.
33
+ 2. **For Developers & Engineers:** Blindly pasting fixes without dissecting the failure mechanism leads to fragile code, cascading bugs, and recurring design flaws.
34
+
35
+ **Socratic Debug changes the paradigm.**
36
+ Instead of dumping walls of red text or spoon-feeding copy-paste solutions, `socratic` intercepts uncaught runtime crashes and launches a **dedicated desktop mentorship window**. Powered by LangGraph, it acts like a personal coding instructor sitting right next to you:
37
+ - It guides you through a progressive, calibrated Socratic dialogue.
38
+ - It asks probing questions that help you spot the exact misconception on your own.
39
+ - It verifies your understanding before finally unlocking defensive programming best practices.
40
+
41
+ ---
42
+
43
+ ## ✨ Features
44
+
45
+ - 🖥️ **Standalone Desktop Window:** Launches an isolated, dark-themed GUI terminal window right at the center of your screen. No terminal clutter.
46
+ - ⚙️ **In-App Settings Drawer & Secret Masking:** Configure models and API keys directly from the GUI with a slide-in settings panel, toggleable secret masking (`👁️`), and instant hot-reloading.
47
+ - ⚡ **Real-Time Auto-Reload & Live Watcher:** Background file monitor (`FileMonitor`) listens for fixes as you edit your code. It handles editor auto-save with a smart typing debounce, validates syntax, and auto-detects solutions live—no manual re-runs needed!
48
+ - 🌍 **Pure Native BiDi & Arabic Support:** Flawlessly displays English and Arabic with full Right-to-Left (RTL) text shaping and formatting.
49
+ - 🎯 **Calibrated Socratic Mentorship:** 3-tier adaptive hints (Observation ➔ Mechanism ➔ Idiomatic Prevention).
50
+ - 🧠 **Smart Evaluator:** Distinguishes between partial observations (e.g., stating a variable's value) and true comprehension before unlocking the defensive code solution.
51
+ - 🔌 **Universal LLM Support:** Plug into local models via **Ollama** (Gemma, Llama, Qwen) or cloud providers via **OpenRouter** / **Google Gemini**.
52
+ - 🏗️ **Clean Decoupled Architecture:** Core agent nodes and exception hooks communicate via an abstract `EventBus`, allowing Socratic to plug cleanly into Desktop GUI, CLI, or future IDE plugins (VS Code, JetBrains).
53
+ - 📊 **Built-in Observability:** Native tracing with **LangSmith** to monitor latency, tokens, and node execution graphs.
54
+ - 🌐 **Cross-Platform:** Runs seamlessly on **Linux**, **macOS**, and **Windows**.
55
+
56
+ ---
57
+
58
+ ## 🚀 Quick Start
59
+
60
+ ### Installation
61
+
62
+ The cleanest, recommended way to install `socratic` globally across your system without virtual environment conflicts:
63
+
64
+ ```bash
65
+ # Recommended (isolated global CLI)
66
+ pipx install socratic-debug
67
+
68
+ # Or via standard pip
69
+ pip install socratic-debug
70
+ ```
71
+
72
+ Alternatively, use the one-line install script:
73
+ ```bash
74
+ # Linux & macOS
75
+ curl -sSL https://raw.githubusercontent.com/mohamedelawakey/socratic/main/install.sh | bash
76
+
77
+ # Windows (PowerShell)
78
+ irm https://raw.githubusercontent.com/mohamedelawakey/socratic/main/install.ps1 | iex
79
+ ```
80
+
81
+ ---
82
+
83
+ ## 🛠️ Usage
84
+
85
+ You can use `socratic` in two distinct ways:
86
+
87
+ ### Method 1: Zero-Code-Change CLI Runner (Recommended)
88
+ You don't need to add any code or imports to your script! Simply prefix your execution:
89
+
90
+ ```bash
91
+ socratic run my_script.py
92
+ ```
93
+ - If your script runs successfully, it outputs normally.
94
+ - If an unhandled exception occurs, the **Socratic Mentor Window** springs to life immediately!
95
+ - Edit your file in your editor (VS Code, PyCharm, etc.)—Socratic will detect your fix live and celebrate your solution!
96
+
97
+ ### Method 2: In-Process Runtime Hook
98
+ If you are building an application or library and want Socratic guidance baked directly into development runs:
99
+
100
+ ```python
101
+ import socratic
102
+ socratic.install()
103
+
104
+ # Your regular application code
105
+ number_1 = 10
106
+ number_2 = 0
107
+ print(number_1 / number_2) # <-- ZeroDivisionError triggers Socratic window!
108
+ ```
109
+
110
+ ---
111
+
112
+ ## ⚙️ Configuration (`.socratic.yaml`)
113
+
114
+ You can configure settings via the in-app **⚙️ Settings** drawer or directly in `.socratic.yaml`:
115
+
116
+ ```yaml
117
+ # LLM Provider: "ollama" or "openrouter"
118
+ provider: "ollama"
119
+ provider_name: "gemma4:31b-cloud"
120
+ provider_link: "http://localhost:11434"
121
+
122
+ # API Key (for cloud providers like OpenRouter)
123
+ api_key: "your_api_key_here"
124
+
125
+ # Mentor Personality & Language ("Arabic" or "English")
126
+ socratic_language: "English"
127
+ socratic_style: "friendly"
128
+
129
+ # Observability with LangSmith (Optional)
130
+ LANGSMITH_TRACING: "true"
131
+ LANGSMITH_API_KEY: "lsv2_pt_..."
132
+ LANGSMITH_PROJECT: "socratic-debug"
133
+ ```
134
+
135
+ ---
136
+
137
+ ## 🤝 Contributing
138
+
139
+ We welcome contributions from developers worldwide! Please review our [CONTRIBUTING.md](CONTRIBUTING.md) guidelines:
140
+ - For feature requests or major changes, **please open a GitHub Discussion or Issue first**.
141
+ - For bug fixes, direct Pull Requests are warmly welcome.
142
+ - Browse our open issues labeled `good first issue` to start contributing.
143
+
144
+ Please note that this project adheres to the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
145
+
146
+ ---
147
+
148
+ ## 📄 License
149
+
150
+ Distributed under the **MIT License**. See [LICENSE](LICENSE) for full details.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "socratic-debug"
7
- version = "0.0.4"
7
+ version = "0.0.5"
8
8
  description = "Autonomous pedagogical debugging mentor powered by LangGraph, Rich, and LangSmith"
9
9
  authors = [{ name = "Mohamed Elawakey" }]
10
10
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: socratic-debug
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: Autonomous pedagogical debugging mentor powered by LangGraph, Rich, and LangSmith
5
5
  Author: Mohamed Elawakey
6
6
  Requires-Python: >=3.10
@@ -18,33 +18,55 @@ Dynamic: license-file
18
18
  # 🧠 Socratic Debug (`socratic`)
19
19
 
20
20
  > **Stop copying stack traces. Start mastering your bugs.**
21
- > An autonomous pedagogical debugger and mentor powered by LangGraph, PyQt6, and LangSmith.
21
+ > An autonomous pedagogical debugger and AI mentor built for **students learning to code** and **developers** who want to truly understand their errors instead of copy-pasting AI patches.
22
22
 
23
23
  [![CI](https://github.com/mohamedelawakey/socratic/actions/workflows/ci.yml/badge.svg)](https://github.com/mohamedelawakey/socratic/actions/workflows/ci.yml)
24
24
  [![PyPI version](https://img.shields.io/pypi/v/socratic-debug.svg?color=blue)](https://pypi.org/project/socratic-debug/)
25
- [![Python Version](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/)
26
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
25
+ [![Python Version](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://www.python.org/)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
27
+ [![LangChain](https://img.shields.io/badge/LangChain-1.4+-1C3C3C?logo=chainlink&logoColor=white)](https://www.langchain.com/)
28
+ [![LangGraph](https://img.shields.io/badge/LangGraph-1.2+-FF8800?logo=diagram-next&logoColor=white)](https://langchain-ai.github.io/langgraph/)
29
+ [![PyQt6](https://img.shields.io/badge/PyQt6-GUI%20Terminal-41CD52?logo=qt&logoColor=white)](https://riverbankcomputing.com/software/pyqt/)
30
+ [![Rich](https://img.shields.io/badge/Rich-Terminal%20UX-blueviolet)](https://github.com/Textualize/rich)
31
+
32
+ [📦 PyPI Package](https://pypi.org/project/socratic-debug/) • [🐛 Report Bug](https://github.com/mohamedelawakey/socratic/issues)
33
+
34
+ ---
35
+
36
+ <p align="center">
37
+ <a href="test/test_hook.py">
38
+ <img src="assets/socratic_ui_demo.png" alt="Socratic Debug Interactive Desktop UI" width="900" style="border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.5);" />
39
+ </a>
40
+ <br />
41
+ <sub>⚡ <em>Interactive debugging session generated live from <a href="test/test_hook.py"><code>test/test_hook.py</code></a></em></sub>
42
+ </p>
27
43
 
28
44
  ---
29
45
 
30
46
  ## 💡 Why Socratic?
31
47
 
32
- When a runtime crash happens, most developers find themselves trapped in one of two extremes:
33
- 1. **The Intimidating Traceback:** Staring at a terrifying wall of 50-line red terminal text, unsure which line actually caused the root flaw.
34
- 2. **The "Copier" Reflex:** Blindly copying the error into an LLM chat, pasting the patch without understanding *why* it failed, only to trigger the exact same design mistake minutes later.
48
+ When a runtime crash happens, both beginners learning to program and seasoned developers often hit a wall:
49
+ 1. **For Students & Beginners:** A 50-line red terminal traceback feels overwhelming and cryptic. In the age of AI, copying the error into an LLM and pasting the generated code creates an illusion of progress—the student passes the assignment but never builds problem-solving intuition or mental models.
50
+ 2. **For Developers & Engineers:** Blindly pasting fixes without dissecting the failure mechanism leads to fragile code, cascading bugs, and recurring design flaws.
35
51
 
36
- **Socratic Debug changes the game.**
37
- Instead of dumping stack traces or spoon-feeding copy-paste patches, `socratic` intercepts uncaught runtime crashes and launches a **dedicated desktop mentorship window**. It analyzes the bug silently and guides you through a calibrated, interactive dialogue to help you **discover, understand, and fix the root cause yourself.**
52
+ **Socratic Debug changes the paradigm.**
53
+ Instead of dumping walls of red text or spoon-feeding copy-paste solutions, `socratic` intercepts uncaught runtime crashes and launches a **dedicated desktop mentorship window**. Powered by LangGraph, it acts like a personal coding instructor sitting right next to you:
54
+ - It guides you through a progressive, calibrated Socratic dialogue.
55
+ - It asks probing questions that help you spot the exact misconception on your own.
56
+ - It verifies your understanding before finally unlocking defensive programming best practices.
38
57
 
39
58
  ---
40
59
 
41
60
  ## ✨ Features
42
61
 
43
- - 🖥️ **Standalone Desktop Window:** Launches an isolated, dark-themed GUI terminal window right at the center of your screen. No terminal pollution.
62
+ - 🖥️ **Standalone Desktop Window:** Launches an isolated, dark-themed GUI terminal window right at the center of your screen. No terminal clutter.
63
+ - ⚙️ **In-App Settings Drawer & Secret Masking:** Configure models and API keys directly from the GUI with a slide-in settings panel, toggleable secret masking (`👁️`), and instant hot-reloading.
64
+ - ⚡ **Real-Time Auto-Reload & Live Watcher:** Background file monitor (`FileMonitor`) listens for fixes as you edit your code. It handles editor auto-save with a smart typing debounce, validates syntax, and auto-detects solutions live—no manual re-runs needed!
44
65
  - 🌍 **Pure Native BiDi & Arabic Support:** Flawlessly displays English and Arabic with full Right-to-Left (RTL) text shaping and formatting.
45
66
  - 🎯 **Calibrated Socratic Mentorship:** 3-tier adaptive hints (Observation ➔ Mechanism ➔ Idiomatic Prevention).
46
67
  - 🧠 **Smart Evaluator:** Distinguishes between partial observations (e.g., stating a variable's value) and true comprehension before unlocking the defensive code solution.
47
68
  - 🔌 **Universal LLM Support:** Plug into local models via **Ollama** (Gemma, Llama, Qwen) or cloud providers via **OpenRouter** / **Google Gemini**.
69
+ - 🏗️ **Clean Decoupled Architecture:** Core agent nodes and exception hooks communicate via an abstract `EventBus`, allowing Socratic to plug cleanly into Desktop GUI, CLI, or future IDE plugins (VS Code, JetBrains).
48
70
  - 📊 **Built-in Observability:** Native tracing with **LangSmith** to monitor latency, tokens, and node execution graphs.
49
71
  - 🌐 **Cross-Platform:** Runs seamlessly on **Linux**, **macOS**, and **Windows**.
50
72
 
@@ -87,6 +109,7 @@ socratic run my_script.py
87
109
  ```
88
110
  - If your script runs successfully, it outputs normally.
89
111
  - If an unhandled exception occurs, the **Socratic Mentor Window** springs to life immediately!
112
+ - Edit your file in your editor (VS Code, PyCharm, etc.)—Socratic will detect your fix live and celebrate your solution!
90
113
 
91
114
  ### Method 2: In-Process Runtime Hook
92
115
  If you are building an application or library and want Socratic guidance baked directly into development runs:
@@ -105,7 +128,7 @@ print(number_1 / number_2) # <-- ZeroDivisionError triggers Socratic window!
105
128
 
106
129
  ## ⚙️ Configuration (`.socratic.yaml`)
107
130
 
108
- When you run `socratic` for the first time, it automatically creates a `.socratic.yaml` config file in your project or home directory:
131
+ You can configure settings via the in-app **⚙️ Settings** drawer or directly in `.socratic.yaml`:
109
132
 
110
133
  ```yaml
111
134
  # LLM Provider: "ollama" or "openrouter"
@@ -117,7 +140,7 @@ provider_link: "http://localhost:11434"
117
140
  api_key: "your_api_key_here"
118
141
 
119
142
  # Mentor Personality & Language ("Arabic" or "English")
120
- socratic_language: "Arabic"
143
+ socratic_language: "English"
121
144
  socratic_style: "friendly"
122
145
 
123
146
  # Observability with LangSmith (Optional)
@@ -129,10 +152,11 @@ LANGSMITH_PROJECT: "socratic-debug"
129
152
  ---
130
153
 
131
154
  ## 🤝 Contributing
132
-
133
- We welcome contributions! Please review our [CONTRIBUTING.md](CONTRIBUTING.md) guidelines:
134
- - For large architectural changes or new features, **please open a GitHub Discussion first**.
135
- - For minor bug fixes, direct Pull Requests are warmly welcome.
155
+
156
+ We welcome contributions from developers worldwide! Please review our [CONTRIBUTING.md](CONTRIBUTING.md) guidelines:
157
+ - For feature requests or major changes, **please open a GitHub Discussion or Issue first**.
158
+ - For bug fixes, direct Pull Requests are warmly welcome.
159
+ - Browse our open issues labeled `good first issue` to start contributing.
136
160
 
137
161
  Please note that this project adheres to the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
138
162
 
@@ -10,8 +10,6 @@ socratic_debug.egg-info/requires.txt
10
10
  socratic_debug.egg-info/top_level.txt
11
11
  src/__init__.py
12
12
  src/cli.py
13
- src/config_creator.py
14
- src/config_template.py
15
13
  src/events.py
16
14
  src/extractor.py
17
15
  src/hook.py
@@ -19,6 +17,7 @@ src/watcher.py
19
17
  src/agent/runner.py
20
18
  src/agent/graph/graph.py
21
19
  src/agent/llm/factory.py
20
+ src/agent/llm/invoker.py
22
21
  src/agent/llm/providers/__init__.py
23
22
  src/agent/llm/providers/ollama.py
24
23
  src/agent/llm/providers/openrouter.py
@@ -33,6 +32,10 @@ src/agent/prompts/mentor_prompt.py
33
32
  src/agent/prompts/questioner_prompt.py
34
33
  src/agent/prompts/solution_prompt.py
35
34
  src/agent/state/state.py
35
+ src/utils/config_creator.py
36
+ src/utils/config_manager.py
37
+ src/utils/config_template.py
38
+ src/utils/config_watcher.py
36
39
  src/utils/read_yaml.py
37
40
  test/test_hook.py
38
41
  ui/__init__.py
@@ -40,6 +43,7 @@ ui/adapter.py
40
43
  ui/app.py
41
44
  ui/bidi.py
42
45
  ui/console.py
46
+ ui/settings_drawer.py
43
47
  ui/styles.py
44
48
  ui/templates.py
45
49
  ui/translations.py
@@ -1,4 +1,5 @@
1
- from src.agent.llm.providers import *
1
+ from src.agent.llm.providers.openrouter import OpenRouterLLM
2
+ from src.agent.llm.providers.ollama import OllamaLLM
2
3
  from src.utils.read_yaml import ReadYaml
3
4
 
4
5
 
@@ -0,0 +1,28 @@
1
+ import os
2
+ import time
3
+ from src.agent.llm.factory import LLMFactory
4
+ from src.events import EventBus
5
+
6
+
7
+ class LLMInvoker:
8
+ @staticmethod
9
+ def invoke_with_retry(prompt: str, max_headless_retries: int = 3):
10
+ is_gui = os.environ.get("SOCRATIC_GUI_ACTIVE") == "1"
11
+ attempts = 0
12
+
13
+ while True:
14
+ if EventBus.is_session_cancelled():
15
+ raise RuntimeError("Session was cancelled by user.")
16
+
17
+ try:
18
+ return LLMFactory.get_llm().invoke(prompt)
19
+ except Exception as e:
20
+ err_msg = str(e)
21
+ EventBus.emit_llm_error(err_msg)
22
+
23
+ if not is_gui:
24
+ attempts += 1
25
+ if attempts >= max_headless_retries:
26
+ raise RuntimeError(f"LLM invocation failed after {attempts} attempts: {err_msg}") from e
27
+
28
+ time.sleep(2)
@@ -7,7 +7,7 @@ class OllamaLLM:
7
7
  def ollama_llm():
8
8
  config = ReadYaml.read_yaml()
9
9
 
10
- return ChatOllama (
10
+ return ChatOllama(
11
11
  model=config["provider_name"],
12
12
  base_url=config["provider_link"],
13
13
  )
@@ -1,6 +1,6 @@
1
1
  from src.agent.prompts.diagnose_prompt import DiagnosePrompt
2
2
  from src.agent.state.state import SocraticAgentState
3
- from src.agent.llm.factory import LLMFactory
3
+ from src.agent.llm.invoker import LLMInvoker
4
4
 
5
5
 
6
6
  class DiagnoseNode:
@@ -16,6 +16,6 @@ class DiagnoseNode:
16
16
  function_name=state.get("function_name") or "",
17
17
  )
18
18
 
19
- response = LLMFactory.get_llm().invoke(prompt)
19
+ response = LLMInvoker.invoke_with_retry(prompt)
20
20
 
21
21
  return {"root_cause": response.content}
@@ -1,6 +1,6 @@
1
1
  from src.agent.prompts.evaluation_prompt import EvaluationPrompt
2
2
  from src.agent.state.state import SocraticAgentState
3
- from src.agent.llm.factory import LLMFactory
3
+ from src.agent.llm.invoker import LLMInvoker
4
4
  from src.events import EventBus
5
5
 
6
6
 
@@ -26,7 +26,7 @@ class EvaluationNode:
26
26
  user_input=user_input,
27
27
  )
28
28
 
29
- response = LLMFactory.get_llm().invoke(prompt)
29
+ response = LLMInvoker.invoke_with_retry(prompt)
30
30
  verdict = response.content.strip().upper()
31
31
 
32
32
  if "SOLVED" in verdict and "UNSOLVED" not in verdict and "NOT SOLVED" not in verdict:
@@ -1,6 +1,6 @@
1
1
  from src.agent.prompts.questioner_prompt import QuestionerPrompt
2
2
  from src.agent.state.state import SocraticAgentState
3
- from src.agent.llm.factory import LLMFactory
3
+ from src.agent.llm.invoker import LLMInvoker
4
4
  from src.utils.read_yaml import ReadYaml
5
5
 
6
6
  from src.events import EventBus
@@ -14,6 +14,9 @@ class QuestionerNode:
14
14
  current_hint = state.get("hint_level", 1)
15
15
  raw_history = state.get("dialogue_history", [])
16
16
 
17
+ # Re-read YAML configuration dynamically to reflect any runtime updates
18
+ live_config = ReadYaml.read_yaml()
19
+
17
20
  formatted_history = "\n".join(
18
21
  f"- {turn.get('role', 'unknown').capitalize()}: {turn.get('content', '')}"
19
22
  for turn in raw_history
@@ -27,11 +30,11 @@ class QuestionerNode:
27
30
  root_cause=state["root_cause"],
28
31
  dialogue_history=formatted_history,
29
32
  hint_level=current_hint,
30
- language=config.get("socratic_language", "English"),
31
- style=config.get("socratic_style", "friendly"),
33
+ language=live_config.get("socratic_language", "English"),
34
+ style=live_config.get("socratic_style", "friendly"),
32
35
  )
33
36
 
34
- response = LLMFactory.get_llm().invoke(prompt)
37
+ response = LLMInvoker.invoke_with_retry(prompt)
35
38
 
36
39
  EventBus.emit_mentor_message(
37
40
  content=response.content,
@@ -1,6 +1,6 @@
1
1
  from src.agent.prompts.solution_prompt import SolutionPrompt
2
2
  from src.agent.state.state import SocraticAgentState
3
- from src.agent.llm.factory import LLMFactory
3
+ from src.agent.llm.invoker import LLMInvoker
4
4
  from src.utils.read_yaml import ReadYaml
5
5
  from src.events import EventBus
6
6
 
@@ -12,17 +12,20 @@ class SolutionNode:
12
12
  def solution_node(state: SocraticAgentState) -> dict:
13
13
  current_status = state.get("eval_status", "solved")
14
14
 
15
+ # Dynamically re-read config to adapt to live changes
16
+ live_config = ReadYaml.read_yaml()
17
+
15
18
  prompt = SolutionPrompt.solution_prompt(
16
19
  error_type=state["error_type"],
17
20
  line_number=state["line_number"],
18
21
  code_snippet=state["code_snippet"],
19
22
  root_cause=state["root_cause"],
20
23
  eval_status=current_status,
21
- language=config.get("socratic_language", "English"),
22
- style=config.get("socratic_style", "friendly"),
24
+ language=live_config.get("socratic_language", "English"),
25
+ style=live_config.get("socratic_style", "friendly"),
23
26
  )
24
27
 
25
- response = LLMFactory.get_llm().invoke(prompt)
28
+ response = LLMInvoker.invoke_with_retry(prompt)
26
29
 
27
30
  EventBus.emit_solution(response.content)
28
31
 
@@ -1,4 +1,4 @@
1
- from typing import TypedDict, List, Dict, Any, Optional
1
+ from typing import TypedDict, List, Dict, Optional
2
2
 
3
3
 
4
4
  class SocraticAgentState(TypedDict):
@@ -64,7 +64,7 @@ def main():
64
64
  sys.exit(0)
65
65
 
66
66
  elif command == "init":
67
- from src.config_creator import create_config
67
+ from src.utils.config_creator import create_config
68
68
  create_config()
69
69
  print("✔ Created .socratic.yaml with default settings.")
70
70
  sys.exit(0)
@@ -8,6 +8,16 @@ class EventBus:
8
8
  _on_evaluator_verdict: Optional[Callable[[str], None]] = None
9
9
  _on_solution: Optional[Callable[[str], None]] = None
10
10
  _on_crash: Optional[Callable[[Dict[str, Any], Any, Any, Any], None]] = None
11
+ _on_llm_error: Optional[Callable[[str], None]] = None
12
+ _is_session_cancelled: bool = False
13
+
14
+ @classmethod
15
+ def emit_session_cancelled(cls):
16
+ cls._is_session_cancelled = True
17
+
18
+ @classmethod
19
+ def is_session_cancelled(cls) -> bool:
20
+ return cls._is_session_cancelled
11
21
 
12
22
  @classmethod
13
23
  def register_handlers(
@@ -17,6 +27,7 @@ class EventBus:
17
27
  on_evaluator_verdict: Optional[Callable[[str], None]] = None,
18
28
  on_solution: Optional[Callable[[str], None]] = None,
19
29
  on_crash: Optional[Callable[[Dict[str, Any], Any, Any, Any], None]] = None,
30
+ on_llm_error: Optional[Callable[[str], None]] = None,
20
31
  ):
21
32
  """Registers presentation callbacks into the Core event bus."""
22
33
  if on_mentor_message:
@@ -29,6 +40,8 @@ class EventBus:
29
40
  cls._on_solution = on_solution
30
41
  if on_crash:
31
42
  cls._on_crash = on_crash
43
+ if on_llm_error:
44
+ cls._on_llm_error = on_llm_error
32
45
 
33
46
  @classmethod
34
47
  def emit_mentor_message(cls, content: str, hint_level: int = 1):
@@ -65,3 +78,10 @@ class EventBus:
65
78
  else:
66
79
  print(f"\n💥 {exc_type.__name__}: {exc_val}")
67
80
  print(f"📍 {context.get('file_path')}:{context.get('line_number')}\n")
81
+
82
+ @classmethod
83
+ def emit_llm_error(cls, err_msg: str):
84
+ if cls._on_llm_error:
85
+ cls._on_llm_error(err_msg)
86
+ else:
87
+ print(f"⚠️ [LLM Error]: {err_msg}")