55 Commits

Author SHA1 Message Date
16d79df421 fix: empty response handling, /no_think model gating, per-model profiles
- Detect empty LLM responses (no content, no tool calls) instead of
  silently treating them as task completion. Retries once without tools
  before warning the user.
- Gate /no_think system message and chat_template_kwargs to Qwen/QwQ
  models only — sending /no_think to llama3.x caused empty responses.
- Add model_profiles config section for per-model overrides (token
  budget, thinking, temperature, max_tokens) matched by name prefix.
  Applied at startup and on /model switch.
- Update SessionManager on /model switch so session files record the
  correct model.
- Add NDJSON fallback in SSE stream parser for Ollama compatibility.
- Improve read_file error to suggest find_files on FileNotFoundError.
- Add diagnostic logging for empty streams and empty results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:09:04 -05:00
1ee721ac10 Merge branch 'bugfix/model-command-regex' 2026-03-11 22:31:50 -05:00
d54a3480b8 fix: /model command no longer incorrectly matched as /mode
Use exact first-word matching instead of startswith() for /models and
/mode command routing. Accept /model as an alias for /models.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 22:31:45 -05:00
d3b286ba40 Merge branch 'feature/file-cache-lru' 2026-03-11 22:26:56 -05:00
d829e6553c feat: add tool-level file cache with LRU eviction and mtime invalidation
Introduces FileCache (OrderedDict LRU, st_mtime_ns validation) to avoid
redundant disk reads and duplicate content in conversation context.
Read tools return a short "[Cached]" message on cache hit instead of
resending unchanged file content, saving tokens. Write/edit/delete tools
invalidate affected paths; str_replace pre-warms the cache after edits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 22:26:51 -05:00
2c532adbbc Merge branch 'feature/read-many-files-and-fixes' 2026-03-11 21:57:39 -05:00
be1ea81102 fix: preserve streaming UI callbacks across agent loop iterations
StreamHandler.reset() was clearing on_content, on_thinking, and on_done
callbacks after every LLM response, but they were only set once per turn.
This caused the thinking indicator and streaming display to stop working
after the first tool call in a multi-step agent turn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:56:59 -05:00
3fe0f7af47 style: change header background from orange to dark cyan
Improves readability of the lightning bolt emoji and gives the header
a distinctive look.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:56:57 -05:00
05754fe06b feat: add read_many_files tool for batch file reading
Reduces LLM round-trips by allowing multiple files to be read in a
single tool call. Uses best-effort error handling so partial failures
still return successful reads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:56:53 -05:00
0886727437 Merge branch 'feature/header-panel-agent-modes' 2026-03-11 21:36:27 -05:00
638aecb561 feat: add custom HeaderPanel widget and switchable agent modes
Replace built-in Header with a custom HeaderPanel showing model name,
mode badge, and live token usage. Add AgentMode enum (normal/plan/auto)
with mode-aware permission gating — Plan mode restricts to read-only
tools, Auto mode auto-approves everything. Includes /mode slash command
and Ctrl+P keybinding to cycle modes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:36:23 -05:00
b878408f3e Merge branch 'fix/remove-cat-allowed-command' 2026-03-11 21:15:05 -05:00
5b5c3098bb fix: remove cat from allowed shell commands and fix stale display tests
Remove cat from allowed_commands to close shell redirect bypass vector
(read_file provides safer alternative). Update display tests to match
render_user_message returning Text instead of Panel, and shell test to
use head instead of cat.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:14:21 -05:00
4e3da84578 Merge branch 'fix/display-bug-and-shell-write-bypass' 2026-03-11 20:58:55 -05:00
2ad3df521d fix: display assistant content with finish tool call + block shell write redirects
Bug 1: Assistant text content was silently dropped when the LLM response
included both content and tool calls (e.g. finish with a summary). Now
content is displayed before tool call execution regardless.

Bug 2: Shell redirect operators (>, >>, <<) allowed bypassing file-write
permissions when the base command (e.g. cat) was in the allowed list.
Redirects now require explicit user approval in permissions, and the
shell tool itself blocks them as defense-in-depth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:58:07 -05:00
4496fce354 docs: update README with full config reference, remove completed roadmap
Expands README with complete config.yaml reference, CLI options table,
skills documentation, and updated command list. Removes the old roadmap
(all phases complete). Updates tweaks.md with current design notes.
Adds .sneakycode/ to .gitignore and includes superpowers design specs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:05:16 -05:00
133bcbda57 feat: re-echo condensed user prompt in chat log
Shows user input as a compact one-liner ("You: prompt text") instead of
a full panel. Multi-line input is collapsed to the first line with a
"(+N lines)" suffix, and long lines are truncated at 120 chars.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:05:10 -05:00
7705008b9c fix: prevent /no_think tag from leaking into user message content
The /no_think directive was appended directly to the user's message text,
causing the LLM to interpret it as user input (e.g., referencing it as a
directory path). Now injected as a separate system message after the last
user message. Also adds which, jq, type, and file to shell allowed_commands
(were mistakenly placed in permissions.auto_approve).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:04:47 -05:00
9273d14845 Merge branch 'feature/disable-thinking-mode' 2026-03-11 19:36:49 -05:00
f0d8ef8f0a feat: add thinking mode toggle to suppress reasoning-only response loops
Adds `llm.thinking` config option (default: true) that when disabled:
- Injects /no_think into the last user message for Qwen 3.x compatibility
- Sends chat_template_kwargs in API payload for backends that support it
- Silently and immediately nudges on reasoning-only responses instead of
  showing warnings and wasting retry iterations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:34:36 -05:00
25fa7dc82b Merge branch 'feature/llm-extra-body-config' 2026-03-11 19:15:39 -05:00
220c6613e4 feat: add extra_body config for model-specific API parameters
Allows passing arbitrary parameters (e.g., enable_thinking, reasoning_effort)
to the LLM API request body via config.yaml, solving reasoning-only response
loops with models like Qwen 3.x without requiring code changes per model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:15:35 -05:00
22f10cd8e9 Merge branch 'feature/structured-skill-packages' 2026-03-11 19:06:13 -05:00
2ae8294e29 feat: structured skill packages with config overrides, chaining, and TUI integration
Add a skill package system where each skill is a directory with a skill.yaml
manifest and prompt markdown files. Skills support /command triggers, scoped
config overrides (temperature, max_tokens, tool filtering), chain dependencies
with cycle-safe resolution, and a finish_skill completion signal.

Includes four built-in skills: explore, brainstorm, write-document, and plan.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:06:05 -05:00
26bcbc6c1f Merge branch 'fix/markdown-rendering-and-reasoning-retry' 2026-03-11 18:21:58 -05:00
cc03f76593 fix: render markdown in assistant panels and speed up reasoning-only recovery
Assistant message panels now use Markdown() instead of raw strings, so
bold/italic/lists render properly. Also nudge the model immediately after
tool errors instead of wasting 2 retry iterations in reasoning-only mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:21:51 -05:00
90a38f12d1 fix: wrap session resume in @work to resolve NoActiveWorker crash
push_screen_wait requires a worker context, but on_mount is a plain
lifecycle callback. Extract session resume logic into a @work-decorated
method so the modal can be awaited without triggering NoActiveWorker.
2026-03-11 15:52:28 -05:00
f93b28215d Merge branch 'feature/tweaks-implementation' 2026-03-11 15:48:10 -05:00
3f9012e6c2 feat: implement tweaks plan - modals, smart shell, spinner, /models, debug log, skills
Phase 1: Permission modal dialog, session resume modal, HistoryInput with
up/down arrow cycling, remove "You:" echo from chat log, LLM client cleanup
on unmount.

Phase 2: Smart shell auto-approve using allowed/denied command lists from
ToolsConfig, animated thinking spinner with live token count in status bar.

Phase 3: /models slash command (list + switch), CLI directory positional
argument, JSONL debug logger with rotation.

Phase 4: Skills system with SkillsManager, load_skill LLM tool, /skills
listing, skill invocation via slash commands, system prompt integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:46:44 -05:00
7600195ecf Merge branch 'feature/textual-tui'
Add Textual TUI replacing the sequential print-and-scroll REPL with a
full terminal UI: fixed input at bottom, scrollable chat log, header
with model info, streaming display, and status bar with token stats.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:42:40 -05:00
13af7565dd fix: write final assistant message to permanent chat log
The streaming widget shows content during streaming then hides on
completion, but nobody was writing the final response to the RichLog.
The assistant message flashed briefly then disappeared.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:55:14 -05:00
bdf7225472 fix: rename _registry to _tool_registry to avoid shadowing Textual internal
The App base class uses _registry (WeakSet) for DOM node tracking.
Our _registry attribute for the tool registry was shadowing it with None,
causing a TypeError during shutdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:53:40 -05:00
a15e428af0 feat: replace REPL loop with Textual TUI launch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:48:10 -05:00
99a15cbd9b feat: add SneakyCodeApp Textual application
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:47:41 -05:00
202466f73d feat: add StatusBar and StreamingStatic widgets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:46:52 -05:00
623ed14cbf feat: add Textual CSS stylesheet for TUI layout
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:46:52 -05:00
641672e4c7 feat: wire AgentLoop to DisplayAdapter and async permissions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:46:28 -05:00
cab3fbc1cf feat: make PermissionsService async with pluggable prompt callback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:44:12 -05:00
021fe340c1 feat: convert StreamHandler to callback-based (remove Rich.Live)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:44:11 -05:00
8335978583 feat: add render functions and DisplayAdapter for TUI display
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:41:04 -05:00
08da2c542a feat: add TUI-safe logging mode that disables RichHandler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:41:03 -05:00
ff40ef7803 feat: add textual dependency for TUI
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:40:59 -05:00
3e88d1d481 Merge branch 'feature/phase-7-polish-hardening' 2026-03-11 10:21:16 -05:00
76ba490aa2 Add Phase 7: polish and hardening — retry, truncation, sessions, shutdown
- Config extensions: retry backoff, truncation threshold, session persistence
- LLM retry with exponential backoff + jitter on transient errors (5xx, connection)
- Conversation truncation: drops oldest messages preserving first user + recent N
- Session persistence: auto-save/restore with atomic writes, cleanup of old files
- Graceful shutdown: SIGTERM handler, cancel() on AgentLoop, save-on-exit
- Partial message recovery on mid-stream interruption
- New slash commands: /save, /session
- 18 new tests (5 retry, 5 truncation, 4 session, 4 integration workflows)
- README.md and docs/tools.md documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:20:16 -05:00
82846d6236 Add .worktrees/ to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:03:27 -05:00
d845fa45a3 Merge branch 'feature/phase-6-write-tools-shell' 2026-03-11 09:45:59 -05:00
f60c47a85f Add Phase 6: write tools, shell, and edit tools with reasoning-only fix
Implement 6 new agent tools — write_file, make_dir, delete_file,
str_replace, patch_apply, run_command — bringing the agent from
read-only observer to active code modifier. All write/shell operations
are gated through the existing permissions service.

Also fix a bug where qwen3.5 thinking mode produces reasoning tokens
but no content after tool results, causing the agent to silently exit.
The loop now detects reasoning-only responses, retries twice, then
injects a nudge message to break the model out of its thinking loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 09:45:48 -05:00
0cf0d01657 file to track little tweaks i want to make after v1 2026-03-11 08:53:55 -05:00
810886effb Merge branch 'bugfix/resolve-safe-path-doubled-prefix' 2026-03-11 08:48:02 -05:00
273da21ef6 Fix doubled workspace path when LLM passes absolute-style relative paths
resolve_safe_path now detects when the LLM passes the workspace root as
a relative path (e.g. "home/user/project/file.py") and strips the prefix
before joining. Also updated the system prompt to explicitly instruct the
model to use relative paths for all tool arguments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 08:47:57 -05:00