Clean up readme, and default config

This commit is contained in:
Alexander R.
2026-07-21 22:51:28 +00:00
parent edfcc872d9
commit 0b7259a011
8 changed files with 43 additions and 35 deletions
+3
View File
@@ -174,3 +174,6 @@ cython_debug/
# PyPI configuration file
.pypirc
# Custom
config.json
+19 -15
View File
@@ -6,21 +6,21 @@
## Overview
**TactiTerm** is an interactive software engineering tutor designed with a "guidance over answers" philosophy. Rather than providing copy-paste solutions, TactiTerm uses a **Socratic AI Mentor** to ask probing questions, provide hints, and guide users toward mastering concepts across 10 programming languages.
**TactiTerm** is an interactive software engineering tutor designed with a "guidance over answers" philosophy. Rather than providing copy-paste solutions, TactiTerm utilizes an **LLM Harness** to ask probing questions, provide hints, and guide users toward mastering concepts across various languages.
TactiTerm features both a rich **Terminal User Interface (TUI)** for command-line productivity and a modern **Web UI** featuring the Monaco Editor.
TactiTerm features both a rich **Terminal User Interface (TUI)** for command-line use, and a modern **Web UI** featuring the Monaco Editor.
---
## Features
- **Socratic AI Mentor:** Provides step-by-step guidance, code review, and conceptual hints without spoiling direct answers.
- **AI Mentor:** Provides step-by-step guidance, code review, and conceptual hints without spoiling direct answers.
- **Dual Interfaces:**
- **TUI:** Built with Python and Textual for high-productivity, keyboard-driven terminal workflows.
- **TUI:** Built with Python and Textual for lightweight, keyboard-driven terminal workflows.
- **Web UI:** Built with React, Vite, TypeScript, Tailwind CSS, and Monaco Editor.
- **10 Supported Languages:** Python, C#, C++, Java, JavaScript, TypeScript, Rust, Lua, HTML, and Go.
- **Real-time Linting & Execution:** Tree-sitter powered syntax validation and safe local code execution.
- **Interactive Syntax Handbook:** W3Schools-style reference catalog with on-demand AI code examples for functions and core language topics.
- **Interactive Syntax Handbook:** Comprehensive reference catalog with on-demand AI code examples for functions and core language topics.
- **AI Challenge Generator (GenTUI):** Create and save custom Markdown programming challenges tailored to specific subjects and difficulties.
- **Configurable & Network Ready:** Easily configure LLM endpoints, ports, and enable `"public": true` to host the Web UI across your local network (`0.0.0.0`).
@@ -30,10 +30,9 @@ TactiTerm features both a rich **Terminal User Interface (TUI)** for command-lin
### Prerequisites
- Python 3.10+
- [`uv`](https://github.com/astral-sh/uv) (Python package runner)
- Node.js & npm (for Web UI)
- [Devbox](https://www.jetify.com/devbox) (optional, for reproducible envs)
- [Devbox](https://www.jetify.com/devbox)
> Currently we only officially support running this through devbox to simplify deployment, though if you have the prequisites installed, you should be able to run TactiTerm without it
### Installation
@@ -45,30 +44,35 @@ TactiTerm features both a rich **Terminal User Interface (TUI)** for command-lin
2. Install dependencies:
```bash
make install
devbox run install
```
*(or `make install` inside `devbox shell`)*
---
## 🎮 Usage
## Usage
TactiTerm is executed via the use of **Devbox** run commands.
### Terminal Interface (TUI)
Launch the interactive terminal application:
```bash
make tui
devbox run tui
```
*(or `make tui` inside `devbox shell`)*
Additional TUI modes:
- `make gentui` - Launch the standalone GenTUI AI Challenge Generator.
- `make tui-debug` - Launch TUI in debug logging mode.
- `devbox run gentui` - Launch the standalone GenTUI AI Challenge Generator.
- `devbox run -- make tui-debug` - Launch TUI in debug logging mode.
### Web Interface (Web UI)
Launch the FastAPI backend server and Vite frontend dev server:
```bash
make web
devbox run web
```
*(or `make web` inside `devbox shell`)*
Then open your browser to `http://localhost:5173`.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"llm": {
"base_url": "http://100.82.205.18:1010/",
"base_url": "http://localhost:8080/",
"model": "local-model",
"api_key": "not-needed",
"temperature": 0.9,
+1
View File
@@ -11,6 +11,7 @@
],
"shell": {
"scripts": {
"install": "make install",
"tui": "make tui",
"gentui": "make gentui",
"web": "make web"
+7 -7
View File
@@ -68,13 +68,13 @@ const Workspace: React.FC<WorkspaceProps> = ({ challengeId, onBack }) => {
const [userQuestion, setUserQuestion] = useState('');
const [isLoadingGuidance, setIsLoadingGuidance] = useState(false);
// Handbook W3Schools state
// Handbook state
const [handbookCatalog, setHandbookCatalog] = useState<HandbookCatalog>({ functions: [], subjects: [] });
const [handbookTab, setHandbookTab] = useState<'functions' | 'subjects'>('functions');
const [searchQuery, setSearchQuery] = useState('');
const [selectedTopic, setSelectedTopic] = useState<HandbookTopic | null>(null);
const [handbookExample, setHandbookExample] = useState<string>(
'Select a built-in function or topic above to view W3Schools reference card...'
'Select a built-in function or topic above to view reference card...'
);
const [isLoadingExample, setIsLoadingExample] = useState(false);
@@ -248,7 +248,7 @@ const Workspace: React.FC<WorkspaceProps> = ({ challengeId, onBack }) => {
if (!currentChallenge) return;
setSelectedTopic(topic);
setIsLoadingExample(true);
setHandbookExample(`⏳ **Generating W3Schools reference card for '${topic.title}' in ${currentChallenge.language}...**\n\n*Consulting LLM backend...*`);
setHandbookExample(`⏳ **Generating reference card for '${topic.title}' in ${currentChallenge.language}...**\n\n*Consulting LLM backend...*`);
try {
const res = await getHandbookExample(currentChallenge.language, topic.id, topic.title);
@@ -392,7 +392,7 @@ const Workspace: React.FC<WorkspaceProps> = ({ challengeId, onBack }) => {
}`}
>
<BookMarked size={14} />
<span>W3Schools Handbook</span>
<span>Syntax Handbook</span>
</button>
</div>
</header>
@@ -634,7 +634,7 @@ const Workspace: React.FC<WorkspaceProps> = ({ challengeId, onBack }) => {
</div>
)}
{/* Right Column Mode 2: W3Schools-Style Handbook Sidebar (Scalable Width) */}
{/* Right Column Mode 2: Handbook Sidebar (Scalable Width) */}
{rightSidebarMode === 'handbook' && (
<div
style={{ width: `${rightWidth}px` }}
@@ -642,7 +642,7 @@ const Workspace: React.FC<WorkspaceProps> = ({ challengeId, onBack }) => {
>
<div className="p-3 border-b border-darkBorder bg-darkBg flex justify-between items-center">
<h2 className="flex items-center gap-2 font-bold text-indigo-400 text-xs uppercase tracking-wider">
<BookMarked size={16} /> W3Schools Reference ({currentChallenge?.language || 'Python'})
<BookMarked size={16} /> Syntax Reference ({currentChallenge?.language || 'Python'})
</h2>
<button
onClick={() => setRightSidebarMode('closed')}
@@ -716,7 +716,7 @@ const Workspace: React.FC<WorkspaceProps> = ({ challengeId, onBack }) => {
)}
</div>
{/* Generated LLM W3Schools Reference Card View */}
{/* Generated LLM Reference Card View */}
<div className="flex-1 p-4 overflow-y-auto">
<div className="p-4 bg-darkBg border border-darkBorder rounded-xl shadow-inner">
<MarkdownView content={handbookExample} />
+1 -1
View File
@@ -144,7 +144,7 @@ class HandbookExampleRequest(BaseModel):
@app.get("/handbook/catalog/{language}")
def get_handbook_catalog_endpoint(language: str):
"""Returns W3Schools-style syntax handbook catalog (functions & subjects) for specified language."""
"""Returns syntax handbook catalog (functions & subjects) for specified language."""
catalog = handbook_service.get_catalog(language)
return {"language": language, "catalog": catalog}
+5 -5
View File
@@ -1,4 +1,4 @@
"""W3Schools-Style Language Reference Handbook service for built-in functions, methods, primitive types, and topics."""
"""Language Reference Handbook service for built-in functions, methods, primitive types, and topics."""
import httpx
from typing import Dict, List, Any
from src.core.config import config
@@ -197,7 +197,7 @@ HANDBOOK_CATALOG: Dict[str, Dict[str, List[Dict[str, str]]]] = {
class HandbookService:
"""W3Schools-Style Language Reference Handbook service."""
"""Language Reference Handbook service."""
def get_catalog(self, language: str) -> Dict[str, List[Dict[str, str]]]:
canonical = registry.canonical_name(language)
@@ -210,7 +210,7 @@ class HandbookService:
lang_name = config_info.get("name", language) if config_info else language
prompt = (
f"Generate a W3Schools-Style Reference Card for '{topic_title}' in {lang_name}.\n"
f"Generate a Reference Card for '{topic_title}' in {lang_name}.\n"
f"Structure your response strictly into these four Markdown sections:\n"
f"1. **Syntax / Signature:** Clear representation of how to invoke or write it.\n"
f"2. **Description & Parameters:** Brief summary of parameter types and return value.\n"
@@ -219,7 +219,7 @@ class HandbookService:
)
sys_prompt = (
"You are an expert W3Schools-Style Documentation Assistant for TactiTerm.\n"
"You are an expert Documentation Assistant for TactiTerm.\n"
"Provide clean, educational reference cards. Ensure the code example is realistic, complete, and copy-pasteable."
)
@@ -259,7 +259,7 @@ class HandbookService:
except Exception as e:
return {
"status": "error",
"message": f"Failed to generate W3Schools reference card via LLM: {e}",
"message": f"Failed to generate reference card via LLM: {e}",
}
+6 -6
View File
@@ -1,4 +1,4 @@
"""TactiTerm TUI — Coding Tutor Terminal User Interface with W3Schools-style Handbook & Expandable Output Terminal."""
"""TactiTerm TUI — Coding Tutor Terminal User Interface with Handbook & Expandable Output Terminal."""
import argparse
import logging
from typing import List, Dict, Any
@@ -336,14 +336,14 @@ class TactiTermTUI(App):
yield MentorInputTextArea(id="mentor-question-input")
yield Button("💡 Ask Mentor (Enter)", id="btn-send-mentor", variant="warning")
# Right column 2: W3Schools-Style Handbook Sidebar
# Right column 2: Handbook Sidebar
with Container(id="handbook-sidebar"):
yield Static("📖 W3Schools Handbook", id="handbook-header")
yield Static("📖 Handbook", id="handbook-header")
yield Input(placeholder="🔍 Search built-ins or topics...", id="handbook-search-input")
yield Button("Filter: All Items (Click to Switch)", id="btn-handbook-mode", variant="default")
yield OptionList(id="handbook_topic_list")
with VerticalScroll(id="handbook-example-scroll"):
yield Markdown("Select a function or topic above to view W3Schools reference card...", id="handbook-example-display")
yield Markdown("Select a function or topic above to view reference card...", id="handbook-example-display")
yield Static("Ready", id="status-bar")
yield Footer()
@@ -524,7 +524,7 @@ class TactiTermTUI(App):
self.load_handbook_catalog(lang)
self.query_one("#handbook_topic_list", OptionList).focus()
self.query_one("#status-bar", Static).update(f"W3Schools Handbook open for {lang}.")
self.query_one("#status-bar", Static).update(f"Handbook open for {lang}.")
def on_mentor_input_text_area_submit_question(
self, event: MentorInputTextArea.SubmitQuestion
@@ -699,7 +699,7 @@ class TactiTermTUI(App):
lang = challenge.language if challenge else "Python"
self.query_one("#handbook-example-display", Markdown).update(
f"⏳ **Generating W3Schools reference card for '{item['title']}' in {lang}...**"
f"⏳ **Generating reference card for '{item['title']}' in {lang}...**"
)
self.run_worker(self._handbook_worker(lang, item["id"], item["title"]))