v1.5.1 — Fix chat system, add system tray icon, agent mode improvements
- Fix Hal chat: add Chat/Agent mode toggle so users can switch between direct LLM streaming (Chat) and tool-using Agent mode - Fix Agent system: graceful degradation when model can't follow structured THOUGHT/ACTION/PARAMS format (falls back to direct answer after 2 parse failures instead of looping 20 times) - Fix frozen build: remove llama_cpp from PyInstaller excludes list so LLM works in compiled exe - Add system tray icon: autarch.ico (from icon.svg) used for exe icons, installer shortcuts, and runtime tray icon - Update tray.py to load .ico file with fallback to programmatic generation - Add inline critical CSS for FOUC prevention - Bump version to 1.5.1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
13cdc5657e
commit
67b7edc696
179
DEVLOG.md
179
DEVLOG.md
@ -5373,3 +5373,182 @@ Added local network discovery so Archon can auto-find AUTARCH servers without ma
|
||||
|
||||
---
|
||||
|
||||
## Session 16 — 2026-03-01: Threat Monitor Enhancement, Hal Agent Mode, Windows Defense, LLM Trainer
|
||||
|
||||
### Phase 4.17 — Threat Monitor Enhancement (7-tab Threat Monitor)
|
||||
|
||||
Expanded the Threat Monitor from 4 tabs to 7, adding Network Intel, Packet Capture, and DDoS Mitigation capabilities.
|
||||
|
||||
**Files Changed:**
|
||||
- `modules/defender_monitor.py` — Added ~15 new methods + singleton `get_threat_monitor()`
|
||||
- `web/routes/defense.py` — Added ~25 new routes under `/defense/monitor/`
|
||||
- `web/templates/defense_monitor.html` — 3 new tabs (7 total), drill-down popups
|
||||
|
||||
**New ThreatMonitor methods:**
|
||||
- `get_bandwidth()` — bytes in/out per interface + deltas (PowerShell / `/proc/net/dev`)
|
||||
- `check_arp_spoofing()` — multiple MACs per IP detection (`arp -a` / `ip neigh show`)
|
||||
- `check_new_listening_ports()` — alert on new listeners since baseline
|
||||
- `geoip_lookup(ip)` — country/ISP/ASN via ipwho.is API
|
||||
- `get_connections_with_geoip()` — connection table enriched with geo data
|
||||
- `get_connection_rate()` — connections/sec trending
|
||||
- `detect_ddos()` — SYN flood / connection flood / bandwidth spike detection
|
||||
- `get_top_talkers(limit)` — top IPs by connection count
|
||||
- `apply_rate_limit(ip, rate)` / `remove_rate_limit(ip)` — per-IP rate limiting (netsh / iptables)
|
||||
- `get_syn_protection_status()` / `enable_syn_protection()` — SYN cookies
|
||||
- `get_ddos_config()` / `save_ddos_config()` — auto-mitigation config (data/ddos_config.json)
|
||||
- `auto_mitigate()` — auto-block offenders if thresholds exceeded
|
||||
- `get_mitigation_history()` / `log_mitigation()` — action log (data/mitigation_log.json)
|
||||
|
||||
**New routes (under `/defense/monitor/`):**
|
||||
- Monitoring: `bandwidth`, `arp-check`, `new-ports`, `geoip`, `connections-geo`, `connection-rate`
|
||||
- Packet Capture: `capture/interfaces`, `capture/start`, `capture/stop`, `capture/stats`, `capture/stream` (SSE), `capture/protocols`, `capture/conversations`
|
||||
- DDoS: `ddos/detect`, `ddos/top-talkers`, `ddos/rate-limit`, `ddos/rate-limit/remove`, `ddos/syn-status`, `ddos/syn-enable`, `ddos/syn-disable`, `ddos/config` (GET/POST), `ddos/auto-mitigate`, `ddos/history`, `ddos/history/clear`
|
||||
|
||||
**7 tabs in defense_monitor.html:**
|
||||
1. **Live Monitor** — enhanced with bandwidth cards, ARP/port/DDoS counters, drill-down popups
|
||||
2. **Connections** — existing, with clickable rows for connection details
|
||||
3. **Network Intel** — bandwidth table, ARP spoof check, listening port monitor, GeoIP lookup, connections+GeoIP
|
||||
4. **Threats** — existing threat list with drill-down
|
||||
5. **Packet Capture** — interface selector, BPF filter, duration, start/stop, live packet SSE stream, protocol distribution, top conversations
|
||||
6. **DDoS Mitigation** — detection status, top talkers, SYN protection toggle, rate limiting per IP, auto-mitigation config, mitigation history
|
||||
7. **Counter-Attack** — existing
|
||||
|
||||
**Drill-down popups (`.tmon-overlay` + `.tmon-popup`):**
|
||||
- Click any stat in Live Monitor → modal popup with detailed data table
|
||||
- Connections popup with clickable rows → individual connection detail card
|
||||
- CSS added: `.tmon-overlay`, `.tmon-popup`, `.tmon-popup-header`, `.tmon-popup-body`, `.tmon-stat-clickable`, `.tmon-detail-card`, `.tmon-row-clickable`, `.tmon-back-btn`
|
||||
|
||||
### Phase 4.18 — Hal Agent Mode + Module Factory
|
||||
|
||||
Wired Hal chat to the Agent system so it can create new AUTARCH modules on demand.
|
||||
|
||||
**Files Changed:**
|
||||
- `core/tools.py` — added `create_module` tool to ToolRegistry
|
||||
- `web/routes/chat.py` — rewritten to use Agent system with system prompt; agent-mode SSE streaming
|
||||
- `data/hal_system_prompt.txt` (NEW) — Hal's codebase knowledge (~2000 tokens)
|
||||
|
||||
**`create_module` tool:**
|
||||
- Validates category (defense/offense/counter/analyze/osint/simulate)
|
||||
- Validates code contains required module attributes (NAME, DESCRIPTION, VERSION, CATEGORY, def run())
|
||||
- Prevents overwriting existing modules
|
||||
- Writes to `modules/{name}.py`
|
||||
- Attempts `importlib.util.spec_from_file_location` to verify valid Python
|
||||
- If import fails, deletes the file and returns the error
|
||||
|
||||
**Chat route rewrite:**
|
||||
- Loads system prompt from `data/hal_system_prompt.txt`
|
||||
- Detects action requests → Agent mode vs simple chat
|
||||
- Agent mode: creates `Agent(llm, tools)`, runs in background thread, streams steps via SSE
|
||||
- SSE events: `thought`, `action`, `result`, `token`, `done`, `error`
|
||||
|
||||
### Phase 4.19 — Windows Defense Sub-Page
|
||||
|
||||
**Files Created:**
|
||||
- `modules/defender_windows.py` — Windows security module with firewall, UAC, Defender AV, services, SSH, NTFS, event logs
|
||||
- `web/templates/defense_windows.html` — multi-tab Windows defense UI
|
||||
|
||||
**Files Changed:**
|
||||
- `web/routes/defense.py` — added `defense.windows_index` route + Windows-specific API routes
|
||||
- `web/templates/base.html` — added Linux/Windows/Threat Monitor sub-items under Defense sidebar
|
||||
|
||||
### Phase 4.20 — LLM Trainer
|
||||
|
||||
**Files Created:**
|
||||
- `modules/llm_trainer.py` — LLM fine-tuning module (dataset management, training config, adapter listing)
|
||||
- `web/routes/llm_trainer.py` — Flask blueprint for LLM Trainer page
|
||||
- `web/templates/llm_trainer.html` — LLM Trainer UI
|
||||
|
||||
**Features:**
|
||||
- Dataset management (create, list, delete JSONL datasets)
|
||||
- Training configuration (model, epochs, learning rate, batch size)
|
||||
- Adapter listing (LoRA/QLoRA adapters)
|
||||
- Training status monitoring
|
||||
|
||||
### Refresh Modules Button
|
||||
|
||||
**Files Changed:**
|
||||
- `web/templates/base.html` — added "Refresh Modules" button in sidebar
|
||||
- `web/static/js/app.js` — `reloadModules()` function POSTs to `/settings/reload-modules`
|
||||
- `web/routes/settings.py` — `POST /settings/reload-modules` route calls `MenuSystem.reload_modules()`
|
||||
|
||||
---
|
||||
|
||||
## Session 17 — 2026-03-02: System Tray, Dual-Exe Build, Installer Scripts, v1.5 Release
|
||||
|
||||
### Phase 4.21 — System Tray Icon
|
||||
|
||||
**Files Created:**
|
||||
- `core/tray.py` — `TrayManager` class using pystray + PIL
|
||||
|
||||
**Files Changed:**
|
||||
- `autarch.py` — added `--no-tray` flag, tray integration in `--web` mode
|
||||
|
||||
**TrayManager features:**
|
||||
- Auto-generates dark circle icon with cyan "A" using PIL
|
||||
- Menu: status line, Start, Stop, Restart, Open Dashboard, Exit
|
||||
- Dynamic menu state (Start disabled when running, Stop/Restart disabled when stopped)
|
||||
- Uses `werkzeug.serving.make_server` for threaded Flask in background
|
||||
- SSL context passthrough for HTTPS
|
||||
- `TRAY_AVAILABLE` flag for graceful fallback on systems without pystray
|
||||
|
||||
### Phase 4.22 — Dual Executable Build + Frozen Path Support
|
||||
|
||||
**Files Created:**
|
||||
- `autarch_web.py` — Windowless web launcher entry point (Win32GUI, no console window)
|
||||
|
||||
**Files Changed:**
|
||||
- `core/paths.py` — Frozen build support with dual-directory pattern
|
||||
- `core/menu.py` — Module loading scans both bundled and user module directories
|
||||
- `web/app.py` — Template/static paths resolve correctly in frozen (PyInstaller) builds
|
||||
|
||||
**Frozen build architecture:**
|
||||
- `_FROZEN = getattr(sys, 'frozen', False)` detection
|
||||
- `_BUNDLE_DIR` = `Path(sys._MEIPASS)` when frozen (read-only assets)
|
||||
- `_APP_DIR` = `Path(sys.executable).parent` when frozen (writable data)
|
||||
- New: `is_frozen()`, `get_bundle_dir()`, `get_user_modules_dir()`
|
||||
- `get_config_path()` copies bundled config to writable location on first run
|
||||
- Module loading: scans both `get_modules_dir()` (bundle) and `get_user_modules_dir()` (user), user overrides bundled
|
||||
|
||||
### Phase 4.23 — Installer Scripts
|
||||
|
||||
**Files Created:**
|
||||
- `installer.iss` — Inno Setup script (lzma2, no solid compression for large files)
|
||||
- `installer.nsi` — NSIS script with MUI2, Start Menu, desktop shortcut, uninstaller
|
||||
|
||||
**Files Changed:**
|
||||
- `autarch_public.spec` — Rewritten for dual-exe build with MERGE/COLLECT, existence-filtered data files
|
||||
- `setup_msi.py` — Dual executables, LocalAppData install, model inclusion
|
||||
|
||||
**PyInstaller spec details:**
|
||||
- Dual Analysis: `a_cli` (autarch.py, console=True) + `a_web` (autarch_web.py, console=False)
|
||||
- `MERGE()` for shared library deduplication
|
||||
- Single `COLLECT` combining both executables
|
||||
- Existence filter: `added_files = [(str(src), dst) for src, dst in _candidate_files if src.exists()]`
|
||||
|
||||
**Inno Setup details:**
|
||||
- GGUF model stored with `Flags: nocompression` to avoid OOM (3.9GB, barely compressible)
|
||||
- `SolidCompression=no` prevents Inno from loading entire archive into memory
|
||||
- Model excluded from main recursive glob with `Excludes: "_internal\models\Hal_v2.gguf"`
|
||||
- GitHub release version excludes model (34 MB vs 3.9 GB)
|
||||
|
||||
### Phase 4.24 — WebUI FOUC Fix
|
||||
|
||||
**Files Changed:**
|
||||
- `web/templates/base.html` — added inline critical CSS in `<head>`
|
||||
|
||||
**Fix:** Inlined dark theme colors, sidebar layout, and flex container styles directly in `<style>` tag before the external stylesheet `<link>`. Prevents flash of unstyled content (white background, unstyled sidebar) when the external CSS is delayed by self-signed cert negotiation or slow loading.
|
||||
|
||||
### v1.5 Release
|
||||
|
||||
**Release:** https://github.com/DigijEth/autarch/releases/tag/v1.5
|
||||
|
||||
**Assets:**
|
||||
- `AUTARCH_Setup.exe` (34 MB) — Inno Setup installer, installs to `%LocalAppData%\AUTARCH`
|
||||
- `AUTARCH_v1.5_Portable.zip` (39 MB) — Portable build with `autarch.exe` + `autarch_web.exe`
|
||||
|
||||
**Note:** Hal AI model (`Hal_v2.gguf`, 3.9 GB) excluded from both downloads due to GitHub's 2 GB per-asset limit.
|
||||
|
||||
**All 27+ pages tested** — inline CSS + external stylesheet present, layout/sidebar/content structure verified on every route.
|
||||
|
||||
---
|
||||
|
||||
|
||||
BIN
autarch.ico
Normal file
BIN
autarch.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@ -29,6 +29,9 @@ _candidate_files = [
|
||||
# LLM model
|
||||
(SRC / 'models' / 'Hal_v2.gguf', 'models'),
|
||||
|
||||
# Icon
|
||||
(SRC / 'autarch.ico', '.'),
|
||||
|
||||
# Root-level config and docs
|
||||
(SRC / 'autarch_settings.conf', '.'),
|
||||
(SRC / 'user_manual.md', '.'),
|
||||
@ -100,7 +103,7 @@ hidden_imports = [
|
||||
|
||||
excludes = [
|
||||
# Exclude heavy optional deps not needed at runtime
|
||||
'torch', 'transformers', 'llama_cpp', 'llama_cpp_python', 'anthropic',
|
||||
'torch', 'transformers',
|
||||
'tkinter', 'matplotlib', 'numpy',
|
||||
# CUDA / quantization libraries
|
||||
'bitsandbytes',
|
||||
@ -171,7 +174,7 @@ exe_cli = EXE(
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
icon=None,
|
||||
icon=str(SRC / 'autarch.ico'),
|
||||
)
|
||||
|
||||
# ── Web executable (NO console window — tray icon only) ─────────────────────
|
||||
@ -192,7 +195,7 @@ exe_web = EXE(
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
icon=None,
|
||||
icon=str(SRC / 'autarch.ico'),
|
||||
)
|
||||
|
||||
# ── Collect everything into one directory ────────────────────────────────────
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
[llama]
|
||||
model_path = C:\she\autarch\models\Hal_v2.gguf
|
||||
model_path = C:\she\autarch\models\darkHal.gguf
|
||||
n_ctx = 2048
|
||||
n_threads = 4
|
||||
n_gpu_layers = 0
|
||||
n_gpu_layers = -1
|
||||
temperature = 0.7
|
||||
top_p = 0.9
|
||||
top_k = 40
|
||||
repeat_penalty = 1.1
|
||||
max_tokens = 1024
|
||||
seed = -1
|
||||
n_batch = 256
|
||||
n_batch = 512
|
||||
rope_scaling_type = 0
|
||||
mirostat_mode = 0
|
||||
mirostat_tau = 5.0
|
||||
mirostat_eta = 0.1
|
||||
flash_attn = false
|
||||
gpu_backend = cpu
|
||||
gpu_backend = vulkan
|
||||
|
||||
[autarch]
|
||||
first_run = false
|
||||
|
||||
@ -249,6 +249,7 @@ PARAMS: {"question": "Your question"}
|
||||
self.conversation.append({"role": "user", "content": f"Task: {task}"})
|
||||
|
||||
step_count = 0
|
||||
parse_failures = 0 # Track consecutive format failures
|
||||
|
||||
while step_count < self.max_steps:
|
||||
step_count += 1
|
||||
@ -275,10 +276,34 @@ PARAMS: {"question": "Your question"}
|
||||
# Parse response
|
||||
try:
|
||||
thought, action, params = self._parse_response(response)
|
||||
parse_failures = 0 # Reset on success
|
||||
except ValueError as e:
|
||||
parse_failures += 1
|
||||
self._log(f"Failed to parse response: {e}", "error")
|
||||
self._log(f"Raw response: {response[:200]}...", "warning")
|
||||
# Add error feedback and continue
|
||||
|
||||
# After 2 consecutive parse failures, the model can't follow
|
||||
# the structured format — treat its response as a direct answer
|
||||
if parse_failures >= 2:
|
||||
# Clean up the raw response for display
|
||||
answer = response.strip()
|
||||
# Remove ChatML tokens if present
|
||||
for tag in ['<|im_end|>', '<|im_start|>', '<|endoftext|>']:
|
||||
answer = answer.split(tag)[0]
|
||||
answer = answer.strip()
|
||||
if not answer:
|
||||
answer = "I could not process that request in agent mode. Try switching to Chat mode."
|
||||
|
||||
self._log("Model cannot follow structured format, returning direct answer", "warning")
|
||||
step = AgentStep(thought="Direct response (model does not support agent format)", tool_name="task_complete", tool_args={"summary": answer})
|
||||
step.tool_result = answer
|
||||
self.steps.append(step)
|
||||
if self.on_step:
|
||||
self.on_step(step)
|
||||
self._set_state(AgentState.COMPLETE)
|
||||
return AgentResult(success=True, summary=answer, steps=self.steps)
|
||||
|
||||
# First failure — give one retry with format correction
|
||||
self.conversation.append({
|
||||
"role": "assistant",
|
||||
"content": response
|
||||
|
||||
31
core/tray.py
31
core/tray.py
@ -9,6 +9,7 @@ Requires: pystray, Pillow
|
||||
import sys
|
||||
import threading
|
||||
import webbrowser
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import pystray
|
||||
@ -18,27 +19,43 @@ except ImportError:
|
||||
TRAY_AVAILABLE = False
|
||||
|
||||
|
||||
def _get_icon_path():
|
||||
"""Find the .ico file — works in both source and frozen (PyInstaller) builds."""
|
||||
if getattr(sys, 'frozen', False):
|
||||
base = Path(sys._MEIPASS)
|
||||
else:
|
||||
base = Path(__file__).parent.parent
|
||||
ico = base / 'autarch.ico'
|
||||
if ico.exists():
|
||||
return ico
|
||||
return None
|
||||
|
||||
|
||||
def create_icon_image(size=64):
|
||||
"""Create AUTARCH tray icon programmatically — dark circle with cyan 'A'."""
|
||||
"""Load tray icon from .ico file, falling back to programmatic generation."""
|
||||
ico_path = _get_icon_path()
|
||||
if ico_path:
|
||||
try:
|
||||
img = Image.open(str(ico_path))
|
||||
img = img.resize((size, size), Image.LANCZOS)
|
||||
return img.convert('RGBA')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Fallback: generate programmatically
|
||||
img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Dark background circle with cyan border
|
||||
draw.ellipse([1, 1, size - 2, size - 2], fill=(15, 15, 25, 255),
|
||||
outline=(0, 180, 255, 255), width=2)
|
||||
|
||||
# Letter "A" centered
|
||||
try:
|
||||
font = ImageFont.truetype("arial.ttf", int(size * 0.5))
|
||||
except OSError:
|
||||
font = ImageFont.load_default()
|
||||
|
||||
bbox = draw.textbbox((0, 0), "A", font=font)
|
||||
tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
||||
x = (size - tw) // 2
|
||||
y = (size - th) // 2 - bbox[1]
|
||||
draw.text((x, y), "A", fill=(0, 200, 255, 255), font=font)
|
||||
|
||||
return img
|
||||
|
||||
|
||||
|
||||
@ -2262,3 +2262,65 @@ Full Hash Toolkit added as a sub-page under Analyze (sidebar sub-item like Legen
|
||||
- **Android Protection Direct mode** — `apDirect()` was passing `HWDirect.adbShell()` result objects (dicts) into `raw` instead of extracting `.stdout` strings; Python `/parse` route then crashed calling `.strip()` on dicts. Fixed by extracting stdout before sending to server
|
||||
- **`_serial()` hardened** — now checks `request.form` fallback and wraps in `str()` before `.strip()`
|
||||
|
||||
---
|
||||
|
||||
## Session 16 — 2026-03-01: Threat Monitor, Hal Agent, Windows Defense, LLM Trainer
|
||||
|
||||
### What got done this session:
|
||||
- **7-tab Threat Monitor** — expanded from 4 tabs to 7 with Network Intel, Packet Capture, DDoS Mitigation
|
||||
- **Drill-down popups** — click any stat in Live Monitor for detailed modal views
|
||||
- **Hal Agent Mode** — Chat bubble now uses Agent system with `create_module` tool; can create modules on demand
|
||||
- **System prompt** — `data/hal_system_prompt.txt` teaches Hal the codebase
|
||||
- **Windows Defense** — `modules/defender_windows.py` + `defense_windows.html` (firewall, UAC, Defender AV, services, SSH, NTFS, event logs)
|
||||
- **LLM Trainer** — `modules/llm_trainer.py` + `web/routes/llm_trainer.py` + `llm_trainer.html` (dataset management, training, adapters)
|
||||
- **Refresh Modules** — sidebar button for hot-reloading modules without server restart
|
||||
|
||||
### Todos from session 14 resolved:
|
||||
- System Tray → deferred to session 17
|
||||
- Beta Release → deferred to session 17
|
||||
|
||||
---
|
||||
|
||||
## Session 17 — 2026-03-02: System Tray, Packaging, v1.5 Release
|
||||
|
||||
### What got done this session:
|
||||
- **System tray** — `core/tray.py` with `TrayManager` (pystray + PIL): Start/Stop/Restart/Open Dashboard/Exit
|
||||
- **Dual executables** — `autarch.exe` (CLI, console) + `autarch_web.exe` (Web, no console, tray icon)
|
||||
- **PyInstaller frozen build fixes** — dual-directory pattern in `core/paths.py` (_BUNDLE_DIR vs _APP_DIR), module loading scans both bundled and user dirs
|
||||
- **Installer scripts** — `installer.iss` (Inno Setup) + `installer.nsi` (NSIS)
|
||||
- **Inno Setup OOM fix** — 3.9GB model stored uncompressed, `SolidCompression=no`
|
||||
- **Inline critical CSS** — prevents white flash / FOUC on page load
|
||||
- **All 27+ pages tested** — verified inline CSS, external stylesheet, layout structure
|
||||
- **Version bumped to 1.5**
|
||||
- **GitHub Release v1.5** — https://github.com/DigijEth/autarch/releases/tag/v1.5
|
||||
- `AUTARCH_Setup.exe` (34 MB) — installer without model
|
||||
- `AUTARCH_v1.5_Portable.zip` (39 MB) — portable without model
|
||||
|
||||
### SESSION SAVE — 2026-03-02 (end of session)
|
||||
|
||||
**Phase status:**
|
||||
- Phases 0–4.24: DONE
|
||||
- Phase 5 (Path portability): DONE (frozen build support complete)
|
||||
- Phase 6 (Docker): NOT STARTED
|
||||
|
||||
**Key files created/modified this session:**
|
||||
- `core/tray.py` (NEW) — TrayManager
|
||||
- `autarch_web.py` (NEW) — Windowless web launcher
|
||||
- `installer.iss` (NEW) — Inno Setup installer script
|
||||
- `installer.nsi` (NEW) — NSIS installer script
|
||||
- `core/paths.py` — Frozen build dual-directory pattern
|
||||
- `core/menu.py` — Dual module directory scanning
|
||||
- `web/app.py` — Frozen template/static path resolution
|
||||
- `autarch.py` — --no-tray flag
|
||||
- `autarch_public.spec` — Dual-exe MERGE/COLLECT
|
||||
- `setup_msi.py` — Dual executables, v1.5
|
||||
- `web/templates/base.html` — Inline critical CSS
|
||||
|
||||
**Todos from session 14 RESOLVED:**
|
||||
- System Tray: DONE (core/tray.py)
|
||||
- Beta Release: DONE (v1.5 on GitHub)
|
||||
|
||||
**Remaining work from master_plan.md:**
|
||||
- Phase 6 (Docker): NOT STARTED
|
||||
- Plan file (quizzical-toasting-mccarthy.md) — Threat Monitor + Hal Module Factory: DONE
|
||||
|
||||
|
||||
87
icon.svg
Normal file
87
icon.svg
Normal file
@ -0,0 +1,87 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||
<defs>
|
||||
<!-- Neon cyan glow -->
|
||||
<filter id="glow">
|
||||
<feGaussianBlur stdDeviation="6" result="blur"/>
|
||||
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
|
||||
</filter>
|
||||
<!-- Heavy outer glow -->
|
||||
<filter id="glowHeavy">
|
||||
<feGaussianBlur stdDeviation="12" result="blur1"/>
|
||||
<feGaussianBlur stdDeviation="24" result="blur2"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="blur2"/>
|
||||
<feMergeNode in="blur1"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<!-- Scanlines pattern -->
|
||||
<pattern id="scanlines" width="4" height="4" patternUnits="userSpaceOnUse">
|
||||
<rect width="4" height="2" fill="rgba(0,255,255,0.03)"/>
|
||||
<rect y="2" width="4" height="2" fill="rgba(0,0,0,0.15)"/>
|
||||
</pattern>
|
||||
<!-- Grid pattern -->
|
||||
<pattern id="grid" width="32" height="32" patternUnits="userSpaceOnUse">
|
||||
<path d="M 32 0 L 0 0 0 32" fill="none" stroke="rgba(0,255,255,0.06)" stroke-width="0.5"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
|
||||
<!-- Dark background -->
|
||||
<rect width="512" height="512" fill="#05080f"/>
|
||||
<!-- Grid overlay -->
|
||||
<rect width="512" height="512" fill="url(#grid)"/>
|
||||
|
||||
<!-- Faint radial ambiance -->
|
||||
<circle cx="256" cy="256" r="240" fill="none" stroke="rgba(255,0,80,0.04)" stroke-width="180"/>
|
||||
<circle cx="256" cy="256" r="180" fill="none" stroke="rgba(0,255,255,0.03)" stroke-width="120"/>
|
||||
|
||||
<!-- Glitch offset layers (red/blue chromatic aberration) -->
|
||||
<g opacity="0.35">
|
||||
<!-- Red offset -->
|
||||
<circle cx="259" cy="254" r="200" fill="none" stroke="#ff0040" stroke-width="20"/>
|
||||
<line x1="259" y1="54" x2="123" y2="428" stroke="#ff0040" stroke-width="20" stroke-linecap="round"/>
|
||||
<line x1="259" y1="54" x2="395" y2="428" stroke="#ff0040" stroke-width="20" stroke-linecap="round"/>
|
||||
<line x1="103" y1="318" x2="415" y2="318" stroke="#ff0040" stroke-width="20" stroke-linecap="round"/>
|
||||
</g>
|
||||
<g opacity="0.35">
|
||||
<!-- Blue offset -->
|
||||
<circle cx="253" cy="258" r="200" fill="none" stroke="#00d4ff" stroke-width="20"/>
|
||||
<line x1="253" y1="58" x2="117" y2="432" stroke="#00d4ff" stroke-width="20" stroke-linecap="round"/>
|
||||
<line x1="253" y1="58" x2="389" y2="432" stroke="#00d4ff" stroke-width="20" stroke-linecap="round"/>
|
||||
<line x1="97" y1="322" x2="409" y2="322" stroke="#00d4ff" stroke-width="20" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Main symbol with neon glow -->
|
||||
<g filter="url(#glowHeavy)">
|
||||
<circle cx="256" cy="256" r="200" fill="none" stroke="#00ffcc" stroke-width="18"/>
|
||||
<line x1="256" y1="56" x2="120" y2="430" stroke="#00ffcc" stroke-width="18" stroke-linecap="round"/>
|
||||
<line x1="256" y1="56" x2="392" y2="430" stroke="#00ffcc" stroke-width="18" stroke-linecap="round"/>
|
||||
<line x1="100" y1="320" x2="412" y2="320" stroke="#00ffcc" stroke-width="18" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Bright core layer -->
|
||||
<g filter="url(#glow)">
|
||||
<circle cx="256" cy="256" r="200" fill="none" stroke="#ffffff" stroke-width="4" opacity="0.6"/>
|
||||
<line x1="256" y1="56" x2="120" y2="430" stroke="#ffffff" stroke-width="4" opacity="0.6" stroke-linecap="round"/>
|
||||
<line x1="256" y1="56" x2="392" y2="430" stroke="#ffffff" stroke-width="4" opacity="0.6" stroke-linecap="round"/>
|
||||
<line x1="100" y1="320" x2="412" y2="320" stroke="#ffffff" stroke-width="4" opacity="0.6" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- Glitch bars -->
|
||||
<rect x="0" y="170" width="512" height="3" fill="#00ffcc" opacity="0.15"/>
|
||||
<rect x="0" y="340" width="512" height="2" fill="#ff0040" opacity="0.12"/>
|
||||
<rect x="0" y="405" width="512" height="1.5" fill="#00ffcc" opacity="0.1"/>
|
||||
<rect x="180" y="168" width="90" height="6" fill="#05080f" opacity="0.8"/>
|
||||
<rect x="300" y="338" width="60" height="5" fill="#05080f" opacity="0.8"/>
|
||||
|
||||
<!-- Scanlines overlay -->
|
||||
<rect width="512" height="512" fill="url(#scanlines)"/>
|
||||
|
||||
<!-- Corner accents -->
|
||||
<g stroke="#00ffcc" stroke-width="2" opacity="0.4">
|
||||
<polyline points="10,40 10,10 40,10" fill="none"/>
|
||||
<polyline points="472,10 502,10 502,40" fill="none"/>
|
||||
<polyline points="10,472 10,502 40,502" fill="none"/>
|
||||
<polyline points="472,502 502,502 502,472" fill="none"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@ -13,8 +13,8 @@
|
||||
|
||||
[Setup]
|
||||
AppName=AUTARCH
|
||||
AppVersion=1.5
|
||||
AppVerName=AUTARCH 1.5
|
||||
AppVersion=1.5.1
|
||||
AppVerName=AUTARCH 1.5.1
|
||||
AppPublisher=darkHal Security Group
|
||||
AppPublisherURL=https://github.com/darkhal
|
||||
AppSupportURL=https://github.com/darkhal
|
||||
@ -32,8 +32,8 @@ DisableProgramGroupPage=yes
|
||||
WizardStyle=modern
|
||||
SetupLogging=yes
|
||||
|
||||
; Uncomment and set path if you have a custom icon:
|
||||
; SetupIconFile=assets\autarch.ico
|
||||
SetupIconFile=autarch.ico
|
||||
UninstallDisplayIcon={app}\autarch_web.exe
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
@ -49,12 +49,12 @@ Source: "dist\autarch\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
||||
|
||||
[Icons]
|
||||
; Start Menu
|
||||
Name: "{group}\AUTARCH Web Dashboard"; Filename: "{app}\autarch_web.exe"; Comment: "Launch AUTARCH Web Dashboard with system tray"
|
||||
Name: "{group}\AUTARCH CLI"; Filename: "{app}\autarch.exe"; Comment: "AUTARCH command-line interface"
|
||||
Name: "{group}\AUTARCH Web Dashboard"; Filename: "{app}\autarch_web.exe"; IconFilename: "{app}\autarch.ico"; Comment: "Launch AUTARCH Web Dashboard with system tray"
|
||||
Name: "{group}\AUTARCH CLI"; Filename: "{app}\autarch.exe"; IconFilename: "{app}\autarch.ico"; Comment: "AUTARCH command-line interface"
|
||||
Name: "{group}\Uninstall AUTARCH"; Filename: "{uninstallexe}"
|
||||
|
||||
; Desktop (optional)
|
||||
Name: "{commondesktop}\AUTARCH Web"; Filename: "{app}\autarch_web.exe"; Tasks: desktopicon; Comment: "Launch AUTARCH Web Dashboard"
|
||||
Name: "{commondesktop}\AUTARCH Web"; Filename: "{app}\autarch_web.exe"; IconFilename: "{app}\autarch.ico"; Tasks: desktopicon; Comment: "Launch AUTARCH Web Dashboard"
|
||||
|
||||
; Windows Startup (optional)
|
||||
Name: "{userstartup}\AUTARCH Web"; Filename: "{app}\autarch_web.exe"; Tasks: startupicon
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
; ── App metadata ─────────────────────────────────────────────────────────────
|
||||
!define APPNAME "AUTARCH"
|
||||
!define APPVERSION "1.5"
|
||||
!define APPVERSION "1.5.1"
|
||||
!define PUBLISHER "darkHal Security Group"
|
||||
!define DESCRIPTION "Autonomous Tactical Agent for Reconnaissance, Counterintelligence, and Hacking"
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ build_exe_options = {
|
||||
'web.routes.targets', 'web.routes.encmodules',
|
||||
'web.routes.llm_trainer',
|
||||
],
|
||||
'excludes': ['torch', 'transformers', 'llama_cpp', 'llama_cpp_python', 'anthropic',
|
||||
'excludes': ['torch', 'transformers',
|
||||
'tkinter', 'matplotlib', 'numpy',
|
||||
'bitsandbytes',
|
||||
'huggingface_hub', 'safetensors', 'tokenizers',
|
||||
@ -74,7 +74,7 @@ bdist_msi_options = {
|
||||
|
||||
setup(
|
||||
name='AUTARCH',
|
||||
version='1.5.0',
|
||||
version='1.5.1',
|
||||
description='AUTARCH — Autonomous Tactical Agent for Reconnaissance, Counterintelligence, and Hacking',
|
||||
author='darkHal Security Group & Setec Security Labs',
|
||||
options={
|
||||
|
||||
@ -45,14 +45,51 @@ def _ensure_model_loaded():
|
||||
@chat_bp.route('/chat', methods=['POST'])
|
||||
@login_required
|
||||
def chat():
|
||||
"""Handle chat messages — uses Agent system for tool-using tasks,
|
||||
direct chat for simple questions. Streams response via SSE."""
|
||||
"""Handle chat messages — direct chat or agent mode based on user toggle.
|
||||
Streams response via SSE."""
|
||||
data = request.get_json(silent=True) or {}
|
||||
message = data.get('message', '').strip()
|
||||
mode = data.get('mode', 'chat') # 'chat' (default) or 'agent'
|
||||
if not message:
|
||||
return jsonify({'error': 'No message provided'})
|
||||
|
||||
# Always use agent mode so Hal can use tools including create_module
|
||||
if mode == 'agent':
|
||||
return _handle_agent_chat(message)
|
||||
else:
|
||||
return _handle_direct_chat(message)
|
||||
|
||||
|
||||
def _handle_direct_chat(message):
|
||||
"""Direct chat mode — streams tokens from the LLM without the Agent system."""
|
||||
def generate():
|
||||
from core.llm import get_llm, LLMError
|
||||
|
||||
llm = get_llm()
|
||||
if not llm.is_loaded:
|
||||
yield f"data: {json.dumps({'type': 'status', 'content': 'Loading model...'})}\n\n"
|
||||
try:
|
||||
llm.load_model(verbose=False)
|
||||
except LLMError as e:
|
||||
yield f"data: {json.dumps({'type': 'error', 'content': f'Failed to load model: {e}'})}\n\n"
|
||||
yield f"data: {json.dumps({'done': True})}\n\n"
|
||||
return
|
||||
|
||||
system_prompt = _get_system_prompt()
|
||||
try:
|
||||
token_gen = llm.chat(message, system_prompt=system_prompt, stream=True)
|
||||
for token in token_gen:
|
||||
yield f"data: {json.dumps({'token': token})}\n\n"
|
||||
except LLMError as e:
|
||||
yield f"data: {json.dumps({'type': 'error', 'content': str(e)})}\n\n"
|
||||
|
||||
yield f"data: {json.dumps({'done': True})}\n\n"
|
||||
|
||||
return Response(generate(), mimetype='text/event-stream',
|
||||
headers={'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no'})
|
||||
|
||||
|
||||
def _handle_agent_chat(message):
|
||||
"""Agent mode — uses the Agent system with tools for complex tasks."""
|
||||
run_id = str(uuid.uuid4())
|
||||
stop_event = threading.Event()
|
||||
steps = []
|
||||
@ -86,7 +123,6 @@ def chat():
|
||||
if step.tool_name and step.tool_name not in ('task_complete', 'ask_user'):
|
||||
steps.append({'type': 'action', 'content': f"{step.tool_name}({json.dumps(step.tool_args or {})})"})
|
||||
if step.tool_result:
|
||||
# Truncate long results for display
|
||||
result = step.tool_result
|
||||
if len(result) > 800:
|
||||
result = result[:800] + '...'
|
||||
|
||||
@ -668,6 +668,50 @@ pre { background: var(--bg-primary); border: 1px solid var(--border); border-rad
|
||||
}
|
||||
.hal-close:hover { color: var(--text, #e0e0e0); background: var(--bg-hover, #2a2a3e); }
|
||||
|
||||
/* Hal mode toggle switch */
|
||||
.hal-mode-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.hal-mode-switch input { display: none; }
|
||||
.hal-mode-slider {
|
||||
width: 28px;
|
||||
height: 14px;
|
||||
background: var(--bg-input, #2a2d3e);
|
||||
border-radius: 7px;
|
||||
position: relative;
|
||||
transition: background 0.2s;
|
||||
border: 1px solid var(--border, #333650);
|
||||
}
|
||||
.hal-mode-slider::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: var(--text-secondary, #888);
|
||||
border-radius: 50%;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
transition: transform 0.2s, background 0.2s;
|
||||
}
|
||||
.hal-mode-switch input:checked + .hal-mode-slider {
|
||||
background: var(--accent, #6366f1);
|
||||
border-color: var(--accent, #6366f1);
|
||||
}
|
||||
.hal-mode-switch input:checked + .hal-mode-slider::after {
|
||||
transform: translateX(14px);
|
||||
background: #fff;
|
||||
}
|
||||
.hal-mode-label {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-secondary, #888);
|
||||
min-width: 36px;
|
||||
}
|
||||
|
||||
.hal-messages {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
|
||||
@ -2109,6 +2109,14 @@ async function hwFactoryFlash() {
|
||||
|
||||
// ── Agent Hal Global Chat Panel ──────────────────────────────────────────────
|
||||
|
||||
var halAgentMode = false; // false = direct chat, true = agent mode
|
||||
|
||||
function halModeChanged(checkbox) {
|
||||
halAgentMode = checkbox.checked;
|
||||
var label = document.getElementById('hal-mode-label');
|
||||
if (label) label.textContent = halAgentMode ? 'Agent' : 'Chat';
|
||||
}
|
||||
|
||||
function halToggle() {
|
||||
var p = document.getElementById('hal-panel');
|
||||
if (!p) return;
|
||||
@ -2133,7 +2141,7 @@ function halSend() {
|
||||
fetch('/api/chat', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({message: msg})
|
||||
body: JSON.stringify({message: msg, mode: halAgentMode ? 'agent' : 'chat'})
|
||||
}).then(function(res) {
|
||||
var reader = res.body.getReader();
|
||||
var dec = new TextDecoder();
|
||||
|
||||
@ -130,7 +130,12 @@
|
||||
{% if session.get('user') %}
|
||||
<div id="hal-panel" class="hal-panel" style="display:none">
|
||||
<div class="hal-header">
|
||||
<span>● Agent Hal</span>
|
||||
<span>● Hal</span>
|
||||
<label class="hal-mode-switch" title="Toggle Agent mode (tools) vs Direct chat">
|
||||
<input type="checkbox" id="hal-mode-toggle" onchange="halModeChanged(this)">
|
||||
<span class="hal-mode-slider"></span>
|
||||
<span class="hal-mode-label" id="hal-mode-label">Chat</span>
|
||||
</label>
|
||||
<button onclick="halToggle()" class="hal-close" title="Close">✕</button>
|
||||
</div>
|
||||
<div id="hal-messages" class="hal-messages"></div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user