Compare commits

...

1 Commits

Author SHA1 Message Date
freemo 3c741d926d docs: add v3.7.0 release documentation and TUI reference
CI / lint (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 32s
CI / build (pull_request) Successful in 21s
CI / security (pull_request) Successful in 56s
CI / helm (pull_request) Successful in 28s
CI / typecheck (pull_request) Successful in 3m58s
CI / unit_tests (pull_request) Successful in 6m14s
CI / docker (pull_request) Successful in 1m30s
CI / coverage (pull_request) Successful in 13m6s
CI / e2e_tests (pull_request) Successful in 17m6s
CI / integration_tests (pull_request) Successful in 21m48s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 55m13s
- CHANGELOG.md: add v3.7.0 release section documenting TUI milestone (M8)
  with Added/Changed/Fixed/Security categories covering all major changes
  from the Unreleased section relevant to this release
- README.md: add Feature Overview table, TUI quick-start guide with
  keybinding reference, and first-plan walkthrough; fix clone URL
- docs/reference/tui.md: new TUI reference covering installation, launch,
  keybindings, input modes (@-references, /commands, !-shell), slash
  command catalog (67 commands / 14 groups), widget inventory, and
  source locations
- docs/reference/tui_persona.md: new persona system reference covering
  Persona schema, PersonaRegistry, PersonaState, slash commands, and
  default persona behaviour
2026-04-02 08:08:31 +00:00
4 changed files with 466 additions and 2 deletions
+68
View File
@@ -2,6 +2,74 @@
## Unreleased
## v3.7.0 — TUI Implementation (2026-04-02)
This release delivers the full Text User Interface (TUI) milestone (M8) per
ADR-044, ADR-045, and ADR-046. The TUI is built on Textual and provides an
interactive terminal application with persona management, slash commands,
context-sensitive help, and fuzzy reference resolution.
### Added
- **TUI application** (`agents tui`): Textual-based interactive terminal UI
with `CleverAgentsTuiApp`, graceful fallback when Textual is not installed,
and a `--headless` mode for startup diagnostics. (#695)
- **Input mode routing**: Three distinct input modes — Normal (`@` references),
Command (`/` slash commands), and Shell (`!` passthrough) — dispatched by
`InputModeRouter` with mode auto-detection. (#695)
- **Persona system**: YAML-backed persona registry (`PersonaRegistry`) with
atomic file writes, file-lock safety, and per-session state tracking
(`PersonaState`). Personas carry actor bindings, argument presets, scoped
project/plan lists, and cycle ordering. (#695)
- **Slash command catalog**: 67 slash commands across 14 groups (Session,
Persona, Scope, Plan, Project, Actor, Resource, Config, Tool, Skill,
Invariant, Profile, Context, Utility) defined in `SlashCommandSpec`
descriptors. (#1002)
- **Slash command overlay**: Interactive overlay widget (`SlashCommandOverlay`)
with fuzzy filtering and keyboard navigation. (#695)
- **Reference picker overlay**: `@`-triggered overlay (`ReferencePickerOverlay`)
for resolving project/plan/resource/actor/tool/skill references with
filesystem-backed catalog and 5-second TTL cache. (#695)
- **Fuzzy search**: `score_match` and `rank_candidates` helpers with
prefix/substring/path-component/difflib scoring and recency boosting. (#695)
- **Context-sensitive help panel**: `F1`-toggled `HelpPanelOverlay` with
mode-aware content (Main Screen, Slash Commands, Reference Picker, Shell
Prompt) and global keybinding reference. (#1013)
- **Persona bar widget**: `PersonaBar` status widget displaying active persona
name, icon, and current argument preset. (#695)
- **Prompt widget**: `PromptInput` with mode indicator and submit handling. (#695)
- **TUI command router**: `TuiCommandRouter` dispatching `/persona` and
`/session` slash commands with DI container integration. (#695)
### Changed
- `agents actor run` now takes positional `<NAME>` and `<PROMPT>` arguments,
aligning with the specification. The previous `--prompt/-p` option is
removed. (#901)
- `SandboxManager.commit_all()` is now an all-or-nothing atomic operation per
specification line 45938. Partial failures trigger LIFO rollback of already-
committed sandboxes. (#925)
- `resource_selection` decision type reclassified as phase-agnostic (valid in
both Strategize and Execute phases), aligning with ADR-007 and ADR-033. (#931)
### Fixed
- Execution environment resolution now honours project-level override
(precedence level 2) per the 6-level precedence chain. (#1080)
- `project context set` missing `--execution-env-priority` flag — setting is
now persisted and displayed by `project context show`. (#1079)
- `list_actions()` now queries the database when persistence is enabled so
actions created by prior CLI invocations are visible. (#760)
- `shell=True` subprocess usage in `cli_coverage_steps.py` replaced with
`shlex.split()` and `shell=False` for command injection prevention. (#734)
### Security
- Template rendering hardened with sandboxed Jinja2 renderer denying attribute
access, function calls, and filters. (#319)
- `CleverAgentsError` base class introduced with structured error types and
secret redaction in error details. (#320)
- Added a context-sensitive TUI help panel overlay toggled by `F1`, with
help content that varies for main-screen, slash-command, reference, and
shell prompt modes. Updated Behave and Robot coverage for help-panel
+67 -2
View File
@@ -6,16 +6,32 @@ CleverAgents is a Python-first automation platform. It provides a unified `agent
- Unified CLI entry points: `cleveragents` and `agents`
- Fast Typer/Click-based interface with parity for help/version behavior
- **Interactive TUI** (`agents tui`) built on Textual with persona management, slash commands, and fuzzy reference resolution
- Behavior-driven coverage via Behave and Robot Framework
- Nox automation for linting, typing, testing, docs, builds, and benchmarks
- MkDocs-powered documentation with CleverAgents branding
## Feature Overview
| Feature | Description |
|---------|-------------|
| **Plan lifecycle** | Full strategize → execute → apply pipeline with LLM actors |
| **Actor system** | YAML-defined actors compiled to LangGraph graphs |
| **Skill registry** | Composable skill bundles with MCP, file, git, and inline tools |
| **Resource system** | DAG-based resource registry with 30+ built-in types (git, fs, container, LSP) |
| **Automation profiles** | Named profiles (manual, cautious, supervised, auto, ci, full-auto) controlling autonomy |
| **Sandbox & checkpoint** | Copy-on-write, overlay-fs, git-worktree, and transaction sandbox strategies |
| **ACMS** | Advanced Context Management System with UKO ontology and 10-stage assembly pipeline |
| **TUI** | Textual terminal UI with personas, slash commands, and `@`-reference picker |
| **A2A / Server** | Agent-to-Agent protocol facade; Kubernetes Helm chart for server deployment |
| **Observability** | LangSmith tracing, structured logging via structlog, audit event bus |
## Quick Start
```bash
# clone the CleverAgents core repository
git clone https://git.cleverthis.com/cleveragents/core.git
cd core
git clone https://git.cleverthis.com/cleveragents/cleveragents-core.git
cd cleveragents-core
# install dependencies
python -m venv .venv
@@ -30,6 +46,55 @@ agents --help
agents --version
```
### First plan
```bash
# initialise the local database
agents init
# register a project
agents project create local/my-project --description "My first project"
# add a git resource
agents resource add git-checkout local/my-repo --url https://github.com/example/repo.git
# link resource to project
agents project link-resource local/my-project local/my-repo
# create an action
agents action create --config examples/actions/simple.yaml
# start a plan
agents plan use local/my-action --project local/my-project
# execute the plan (requires an LLM API key)
agents plan execute
```
### Interactive TUI
```bash
# install the optional Textual dependency
pip install 'cleveragents[tui]'
# launch the TUI
agents tui
# headless startup check (no Textual required)
agents tui --headless
```
Inside the TUI:
| Key / Prefix | Action |
|---|---|
| `F1` | Toggle context-sensitive help panel |
| `/` | Open slash command overlay (67 commands) |
| `@` | Open reference picker (projects, plans, resources, …) |
| `!` | Shell passthrough mode |
| `Tab` | Cycle to next persona |
| `Ctrl+Q` | Quit |
## Developing
Pre-commit hooks run automatically on every `git commit` (formatting, linting, type
+212
View File
@@ -0,0 +1,212 @@
# TUI — Text User Interface
The CleverAgents TUI is a Textual-based interactive terminal application
launched with `agents tui`. It provides a full-screen chat-style interface
with persona management, slash commands, `@`-reference resolution, and
context-sensitive help.
**ADRs**: [ADR-044](../adr/ADR-044-tui-architecture-and-framework.md),
[ADR-045](../adr/ADR-045-tui-persona-system.md),
[ADR-046](../adr/ADR-046-tui-reference-and-command-system.md)
## Installation
Textual is an optional dependency:
```bash
pip install 'cleveragents[tui]'
```
Without Textual, `agents tui` raises a `RuntimeError` with installation
instructions. The `--headless` flag works without Textual and is useful for
CI startup checks.
## Launching
```bash
# Full interactive TUI
agents tui
# Headless startup check — prints JSON diagnostics and exits
agents tui --headless
```
The `--headless` output includes:
```json
{
"textual_available": true,
"persona_count": 2,
"default_persona": "default",
"help": "Commands: /persona, /session, /help"
}
```
## Keybindings
| Key | Action |
|-----|--------|
| `F1` | Toggle context-sensitive help panel |
| `Escape` | Close current overlay / return to prompt |
| `Enter` | Submit prompt |
| `Tab` | Cycle to next persona |
| `Ctrl+Tab` | Cycle to next argument preset |
| `Ctrl+Q` | Quit TUI immediately |
## Input Modes
The prompt auto-detects the input mode from the first character:
| Prefix | Mode | Behaviour |
|--------|------|-----------|
| *(none)* | **Normal** | Expands `@`-references and sends to the active actor |
| `/` | **Command** | Opens slash command overlay; dispatches on `Enter` |
| `!` or `$` | **Shell** | Executes the remainder as a shell command |
Mode detection is handled by `InputModeRouter.detect_mode()`.
### Normal mode — `@` references
Type `@` followed by a partial name to open the Reference Picker overlay.
Candidates are drawn from a filesystem-backed catalog (projects, plans,
resources, actors, tools, skills) with a 5-second TTL cache. Fuzzy matching
uses prefix → substring → path-component → difflib scoring with recency
boosting.
```
@my-proj # resolves to project:local/my-project
@main-repo # resolves to resource:local/main-repo
```
Resolved references are expanded inline before the prompt is submitted.
### Command mode — `/` slash commands
Type `/` to open the Slash Command overlay. Start typing to filter the 67
available commands across 14 groups. Press `Enter` to dispatch.
See [Slash Commands](#slash-commands) for the full catalog.
### Shell mode — `!` passthrough
```
! git status
! ls -la
```
The command is executed in a subprocess with a configurable timeout
(default: 30 seconds). Output is displayed in the transcript.
## Slash Commands
67 commands across 14 groups. All commands follow the `group:action` naming
convention.
| Group | Commands |
|-------|---------|
| **Session** | `session:create`, `session:list`, `session:show`, `session:switch`, `session:close`, `session:delete`, `session:rename`, `session:export`, `session:import` |
| **Persona** | `persona:list`, `persona:set`, `persona:create`, `persona:edit`, `persona:delete`, `persona:export`, `persona:import` |
| **Scope** | `scope:add`, `scope:remove`, `scope:clear`, `scope:show` |
| **Plan** | `plan:use`, `plan:list`, `plan:status`, `plan:tree`, `plan:execute`, `plan:apply`, `plan:cancel`, `plan:diff`, `plan:correct`, `plan:resume`, `plan:revert`, `plan:rollback`, `plan:explain`, `plan:errors`, `plan:artifacts`, `plan:inspect` |
| **Project** | `project:list`, `project:create`, `project:show`, `project:delete`, `project:inspect`, `project:context:show` |
| **Actor** | `actor:list`, `actor:show`, `actor:set-default` |
| **Resource** | `resource:list`, `resource:show`, `resource:tree`, `resource:inspect` |
| **Config** | `config:list`, `config:get`, `config:set` |
| **Tool** | `tool:list`, `tool:show` |
| **Skill** | `skill:list`, `skill:show` |
| **Invariant** | `invariant:list`, `invariant:add`, `invariant:remove` |
| **Profile** | `profile:list`, `profile:show` |
| **Context** | `context:inspect`, `context:set` |
| **Utility** | `help`, `clear`, `exit` |
## Widgets
### `CleverAgentsTuiApp`
The root Textual application. Composes:
- `Header` — application title bar
- `PersonaBar` — active persona name, icon, and preset indicator
- `PromptInput` — multi-mode prompt with mode indicator
- `SlashCommandOverlay``/`-triggered command picker
- `ReferencePickerOverlay``@`-triggered reference picker
- `HelpPanelOverlay``F1`-toggled context-sensitive help
- `Footer` — keybinding hints
### `PersonaBar`
Displays the active persona's `icon` and `name` plus the current argument
preset name. Updates automatically when the persona or preset changes.
### `PromptInput`
Single-line input widget. Displays a mode indicator (`>` normal, `/` command,
`!` shell) and emits `InputSubmittedEvent` on `Enter`.
### `SlashCommandOverlay`
Fuzzy-filtered list of all 67 slash commands. Keyboard-navigable. Dismissed
by `Escape`.
### `ReferencePickerOverlay`
Fuzzy-filtered list of catalog entries. Dismissed by `Escape` or on
reference selection.
### `HelpPanelOverlay`
Context-sensitive help panel. Content varies by current mode:
- **Main Screen** — global keybindings + main-screen shortcuts
- **Slash Commands** — slash command navigation hints
- **Reference Picker** — reference picker navigation hints
- **Shell Prompt** — shell mode usage notes
## Source Locations
```
src/cleveragents/tui/
├── app.py # CleverAgentsTuiApp, SessionView, _FallbackCleverAgentsTuiApp
├── commands.py # TuiCommandRouter, run_tui()
├── slash_catalog.py # SLASH_COMMAND_SPECS, SlashCommandSpec
├── cleveragents.tcss # Textual CSS stylesheet
├── input/
│ ├── modes.py # InputMode, InputModeRouter, ModeResult
│ ├── reference_parser.py # ReferenceMatch, ReferenceParseResult, parse_references()
│ └── shell_exec.py # ShellResult, run_shell_command()
├── persona/
│ ├── schema.py # Persona, PersonaPreset
│ ├── registry.py # PersonaRegistry
│ └── state.py # PersonaState
├── search/
│ └── fuzzy.py # FuzzyCandidate, score_match(), rank_candidates()
└── widgets/
├── help_panel_overlay.py # HelpPanelOverlay, resolve_help_context()
├── persona_bar.py # PersonaBar
├── prompt.py # PromptInput
├── reference_picker.py # ReferencePickerOverlay
└── slash_command_overlay.py # SlashCommandOverlay
```
## Running Tests
### Behave (BDD unit tests)
```bash
nox -s unit_tests -- features/tui_persona.feature
nox -s unit_tests -- features/tui_slash_commands.feature
nox -s unit_tests -- features/tui_input_modes.feature
```
### Robot Framework (smoke / integration tests)
```bash
nox -s integration_tests -- robot/tui_smoke.robot
```
## Related
- [Persona System](tui_persona.md) — detailed persona management reference
- [ADR-044](../adr/ADR-044-tui-architecture-and-framework.md) — TUI architecture decisions
- [ADR-045](../adr/ADR-045-tui-persona-system.md) — persona system design
- [ADR-046](../adr/ADR-046-tui-reference-and-command-system.md) — reference and command system
+119
View File
@@ -0,0 +1,119 @@
# TUI Persona System
Personas are named configurations that bind a TUI session to a specific actor,
argument preset, and project/plan scope. They are stored as YAML files under
`~/.config/cleveragents/personas/` and managed by `PersonaRegistry`.
**ADR**: [ADR-045](../adr/ADR-045-tui-persona-system.md)
## Persona Schema
```yaml
name: my-persona # required; no path separators or control chars
description: "..." # optional human-readable description
icon: "🤖" # optional display icon
actor: openai/gpt-4o # required; must be namespaced (namespace/name)
color: "#4CAF50" # optional hex color for UI theming
base_arguments: # default CLI argument overrides
format: json
log_level: warning
scoped_projects: # project names pre-loaded into session scope
- local/my-project
scoped_plans: # plan IDs pre-loaded into session scope
- 01JXYZ...
argument_presets: # named override bundles (Tab cycles through these)
- name: default
display: "default"
overrides: {}
- name: verbose
display: "verbose"
overrides:
log_level: debug
format: rich
cycle_order: 0 # sort order for Tab cycling (lower = earlier)
greeting: "Hello!" # optional greeting shown on persona activation
```
### Field validation
| Field | Constraint |
|-------|-----------|
| `name` | Non-empty; no `/`, `\`, `..`, null bytes, or control characters |
| `actor` | Must contain `/` (namespaced reference) |
| `argument_presets` | Auto-populated with a `default` preset if empty |
## PersonaRegistry
`PersonaRegistry` manages YAML files in `~/.config/cleveragents/personas/`
(overridable via `CLEVERAGENTS_CONFIG_DIR`).
### Key methods
| Method | Description |
|--------|-------------|
| `list_personas()` | Return all valid personas sorted by `cycle_order` then `name` |
| `get(name)` | Return a `Persona` by name, or `None` if not found |
| `save(persona)` | Atomically write persona YAML (temp-file + rename) |
| `delete(name)` | Remove persona YAML file |
| `ensure_default()` | Create and return the built-in `default` persona if absent |
| `get_last_persona()` | Return the last-active persona name from `tui-state.yaml` |
| `set_last_persona(name)` | Persist the last-active persona name |
File writes use `fcntl.LOCK_EX` for concurrent-access safety and an atomic
temp-file rename pattern to prevent partial writes.
## PersonaState
`PersonaState` tracks the active persona and argument preset per TUI session
in memory. It is not persisted across TUI restarts (the last-active persona
name is persisted separately via `PersonaRegistry.set_last_persona()`).
### Key methods
| Method | Description |
|--------|-------------|
| `active_name(session_id)` | Return the active persona name for a session |
| `active_persona(session_id)` | Return the full `Persona` object |
| `set_active_persona(session_id, name)` | Switch active persona; raises `ValueError` if unknown |
| `current_preset(session_id)` | Return the active preset name |
| `cycle_preset(session_id)` | Advance to the next preset in the persona's list |
## Slash commands
Personas are managed via `/persona:*` slash commands in the TUI:
| Command | Description |
|---------|-------------|
| `/persona:list` | Display all personas |
| `/persona:set <name>` | Switch active persona |
| `/persona:create` | Create a new persona |
| `/persona:edit <name>` | Edit an existing persona |
| `/persona:delete <name>` | Delete a persona |
| `/persona:export <name>` | Export persona YAML to stdout |
| `/persona:import` | Import persona YAML from stdin |
## Default persona
If no personas exist, `PersonaRegistry.ensure_default()` creates a built-in
`default` persona bound to the globally configured default actor. This ensures
the TUI always has at least one usable persona on first launch.
## Source Locations
```
src/cleveragents/tui/persona/
├── schema.py # Persona, PersonaPreset (Pydantic models)
├── registry.py # PersonaRegistry (YAML file management)
└── state.py # PersonaState (in-memory session tracking)
```
## Running Tests
```bash
nox -s unit_tests -- features/tui_persona.feature
```
## Related
- [TUI Overview](tui.md) — full TUI reference
- [ADR-045](../adr/ADR-045-tui-persona-system.md) — persona system design decisions