Commit Graph

100 Commits

Author SHA1 Message Date
Levi Neely bda779380e anvilmcp: use single quotes for bash arg escaping
Prevents shell variable expansion in tool args. $VAR now stays
literal instead of expanding to empty string.
2026-03-06 15:03:26 +01:00
Levi Neely fc6cca01a8 Remove Go language support from execute_code (go run lacks stdin)
Keep code extensible for future language support.
2026-03-06 14:15:51 +01:00
Levi Neely b3bb801b23 execute_code: add tool/args params, read from 9P, trust tools
- Add 'tool' param to read tool code from 9P namespace
- Add 'args' as array (passed as positional params via set --)
- Tools from 9P skip dangerous pattern validation (trusted)
- Add Go language support
- Update all skills to use tool/args syntax
2026-03-06 14:07:16 +01:00
Levi Neely b21c56b960 anvilmcp: use layered sandbox config from sandbox package
Reuse the same layered config approach as anvilsrv:
- global.yaml provides base permissions (including /usr, /lib, /bin)
- sandbox/<name>.yaml adds sandbox-specific permissions
- Merge uses most-permissive-wins strategy

This fixes the fallback to default sandbox, which now has proper
system paths from global.yaml.
2026-03-06 10:18:31 +01:00
Levi Neely 2046bc2513 anvilmcp: fallback to default sandbox on permission errors
When sandbox is not explicitly specified, retry with 'default' sandbox
if the initial execution fails with permission denied or missing file errors.
This allows third-party skills designed for execute_bash to work without
modification while preserving isolation when sandbox is explicitly set.
2026-03-06 10:03:01 +01:00
Levi Neely 0d847f96f3 execute_code: configurable sandbox, fix dangerous patterns
- Add sandbox parameter to execute_code (default: anvilmcp)
- Load sandbox config from ~/.config/anvillm/sandbox/<name>.yaml
- Fallback to ./cfg/sandbox/<name>.yaml for development
- Add cwd config option: 'temp' for isolated workspace, '{CWD}' for caller's dir
- Create cfg/sandbox/anvilmcp.yaml with restricted defaults
- Update cfg/sandbox/default.yaml with cwd: '{CWD}'

Dangerous pattern fixes (bash, not JS/Python):
- Remove curl/wget block (network controlled by landrun)
- Remove chmod 777, eval(), exec() (wrong syntax)
- Allow /etc/passwd (world-readable, needed for user lookups)
- Fix /dev/ write check to only block /dev/sd* (not /dev/null)
- Fix eval pattern for actual bash usage

Update skills with explicit sandbox specifications:
- anvilmcp sandbox for normal operations
- default sandbox for spawn_agent.sh (needs full permissions)
2026-03-06 09:53:41 +01:00
Levi Neely d0c596dcaa Add mail_history.sh script for parsing agent message history 2026-03-05 17:08:55 +01:00
Levi Neely 6475b9f216 Add maildir messaging support for agent communication 2026-03-05 14:33:47 +01:00
Levi Neely c0d09125ca Add backend-specific handlers for clear, compact, resume commands
- Add ClearHandler, CompactHandler, ResumeHandler callbacks to tmux.Config
- kiro-cli: clear/resume need 250ms delay + confirmation key
- claude: clear/compact are simple /command[ENTER], resume not implemented
- Add Resume tag and handler to Assist prompt window
- Update server.go to use new Session methods
2026-03-05 09:41:05 +01:00
Levi Neely e3a63dedd8 tmux backend and p9 server improvements 2026-03-05 09:32:07 +01:00
Levi Neely 33026360b3 Assist: reset view to top after refreshing window content
Add w.Addr("0")/dot=addr/show after content writes in refreshList,
refreshMailboxWindow, refreshDaemonWindow, and refreshViewBeadWindow
so windows no longer scroll to the bottom on open or refresh.

Closes anv-hww

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 18:42:07 +01:00
Levi Neely ba5fd04025 fix: make beads mount work with lazy initialization
- Changed NewServer to accept *BeadsFS instead of bd.Storage
- BeadsFS is always created but with no initial mounts
- Each mount opens its own store on-demand
- Added nil check in supervisor to handle missing beads gracefully
2026-03-01 00:47:13 +01:00
Levi Neely 33dbc312b0 fix: remove eager beads store initialization at startup
The beads store was being opened unconditionally at startup, causing
crashes when the database was corrupted or incompatible. Now it's only
opened on-demand when actually needed.
2026-03-01 00:41:39 +01:00
Levi Neely afe13afba2 Fix 9p tool access in execute_code sandbox
- Add DISPLAY, WAYLAND_DISPLAY, USER to landrun env passthrough
- Mount /etc/passwd read-only for getuser() to work
- Update mcptools scripts to check /etc/shadow instead of /etc/passwd for sandbox detection
2026-02-28 20:49:42 +01:00
Levi Neely 95efd907fb Add frontend support for mountable beads and remove global mount state
- Add mount management UI to all frontends (anvillm TUI, Assist, anvilwebgw, anvillm.el)
- Mount commands default to directory basename if name not specified
- Server validates directory exists before mounting
- Umount accepts either mount name or cwd path
- Fix server bug: all beads operations now use mount-specific store
- Remove currentMount global - all operations require explicit mount parameter
- Each Tasks window tracks its own windowMount independently
- Bead detail windows receive mount from parent window
- When no mounts exist, show instructions to mount a project
- When unmounting current mount, switch to first available or show empty state
- Mount validation: Select command checks mount exists before switching
- Database path: ~/.beads/<cwd-hyphenated> to prevent cross-contamination
2026-02-28 13:35:46 +01:00
Levi Neely 1e3623920e Add mountable beads projects with per-project databases
- Mount projects: echo "mount /path/to/project name" | 9p write agent/beads/ctl
- Unmount: echo "umount name" | 9p write agent/beads/ctl
- All beads endpoints work in mounts (list, ready, pending, blocked, etc.)
- Add agent/beads/mtab for mount discovery (mount→cwd mappings)
- Store databases at ~/.beads/<cwd-hyphenated> to prevent cross-contamination
- Supervisor auto-assigns claimable beads to idle bots with matching cwd
- Fix supervisor duplicate messages (track assigned beads, filter by assignee)
- Update beads skill with mtab discovery pattern
- Fix race conditions and add proper locking for mount access
2026-02-28 11:35:19 +01:00
Levi Neely cbace3407c Update changes 2026-02-27 12:12:08 +01:00
Levi Neely 0b612aa0cc Add logging.Init() to all cmd programs
- anvilwebgw: init logging in startCmd
- anvilweb: init logging in main
- anvillm: init logging in main
- Assist: init logging in main

Each program now creates its own timestamped log file
2026-02-27 11:51:50 +01:00
Levi Neely 2111f19e9f Add zap logging to ~/.config/anvillm/logs with panic recovery
- Created internal/logging package with zap logger
- Added panic recovery to anvilsrv main loop, monitor goroutine, and mail processing
- Replaced log.Printf/Fatal with zap in debug, p9, tmux packages
- Fixed beads race condition: clear assignee before closing issue
- All errors and crashes now logged to ~/.config/anvillm/logs
2026-02-27 11:46:49 +01:00
Levi Neely f252aa9452 Add sandbox enforcement to mcptools scripts 2026-02-27 00:25:01 +01:00
Levi Neely 17ec56fbdd Update messaging skill and execute command 2026-02-27 00:06:13 +01:00
Levi Neely e1df81fda6 Compress skills and add network tools
- Compressed skills to <500 tokens each (except rc-shell at 591)
  - beads: 535→59 lines (89% reduction)
  - rc-shell: 270→98 lines (64% reduction)
  - acme-api: 228→85 lines (63% reduction)
  - write-skills: 141→71 lines (50% reduction)
  - github-cli: 133→76 lines (43% reduction)
  - agent-kb: 111→70 lines (37% reduction)
  - jira-to-beads: 129→49 lines (62% reduction)
  - github-to-beads: 109→49 lines (55% reduction)

- Added mcptools for network operations
  - jira-to-beads: fetch Jira hierarchy, create beads
  - github-to-beads: fetch GitHub issues, parse task lists, create beads

- Updated execute_code landrun permissions
  - Added --unrestricted-network for API calls
  - Added user bin dirs: ~/bin, ~/.local/bin, ~/opt, ~/go/bin, $PLAN9/bin

- Documented beads delete behavior (no cascade)

Total token savings: ~2,400 tokens across all skills
2026-02-26 20:02:24 +01:00
Levi Neely 8b87e3514a Move tool scripts from cmd/anvilmcp to mcptools/ 2026-02-26 14:36:50 +01:00
Levi Neely 5f8c41b576
Implement MCP code execution pattern (#20)
* Implement MCP code execution pattern

- Add execute_code tool for bash execution in landrun sandbox
- Remove redundant MCP tools (read_inbox, send_message, etc.)
- Implement dynamic tool discovery from ~/.config/anvillm/mcptools/
- Add workspace isolation (~/.cache/anvillm/exec)
- Add security: output limits, concurrency limits, validation, path traversal protection
- Update bot templates (Conductor, Taskmaster) with bash examples
- Update anvillm-communication skill to use execute_code pattern
- Create comprehensive documentation (user guide, migration guide, security guide)
- Add test suite for validation and limitedWriter
- Fix landrun flags: --rox for executables, --env for AGENT_ID passthrough
- Network blocked by default (no --connect-tcp or --unrestricted-network)

Token reduction: 80-99% via progressive tool discovery and subprocess data processing

* Fix code review issues in MCP code execution pattern

- Security: Change security.jsonl permissions from 0644 to 0600
- Bug: Fix limitedWriter to return correct byte count for io.Copy
- Bug: Fix tool schema inconsistency (execute_code requires only 'code')
- Performance: Move whitespace regex to package-level var
- Security: Improve validateCode with regex patterns and normalization
- Cleanup: Remove dead code from main.go and tools.go
- Cleanup: Rewrite shell scripts to use jq for safe JSON construction
- Docs: Fix duplicate sections and JavaScript syntax in bash examples

* Improve code validation security patterns

- Fix rm -rf bypass: allow optional whitespace before /
- Expand rm -rf to block sensitive paths (/home, /var, /usr, etc.)
- Block all network protocols in curl/wget (not just http/https)
- Add test for regex pattern compilation
- Add test cases for tabs, sensitive paths, ftp/file protocols

* Harden shell scripts and improve rate limiting

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Levi Neely <lneely@pascom.net>
2026-02-26 14:02:54 +01:00
Levi Neely 2418f12012 Fix review findings from code review
- Include model in session list output (eliminates N+1 reads)
- Add jq error handling in Supervisor dispatch_ready_beads
- Use process substitution in Supervisor to avoid subshell variable scope
- Fix claude backend Execute to return error (commands go through PTY)
- Make createSubtask return childID (eliminates duplicate O(n) scan)

Fixes: bd-1z2, bd-73r, bd-cid, bd-viu, bd-vdi
2026-02-26 12:05:28 +01:00
Levi Neely 5bcaa38ad7 cost / usage optimization, phase 1 2026-02-25 19:17:50 +01:00
Levi Neely 50ae907741 anvilwebgw: read message timestamp from JSON instead of filename 2026-02-25 15:03:36 +01:00
Levi Neely 74eec073d3 anvilwebgw: fix session list field mapping (alias/backend swap) 2026-02-25 14:57:27 +01:00
Levi Neely 572ac91d86 Set CLAUDE_CONFIG_DIR at startup and propagate to tmux/shell/sandbox
- anvilsrv sets CLAUDE_CONFIG_DIR to ~/.config/anvillm/claude on start
  if not already set in the environment
- Claude backend includes CLAUDE_CONFIG_DIR in its Environment map so
  it is set in the tmux session and exported to the shell
- tmux backend now exports all b.cfg.Environment vars to the shell
  (via sendKeys) in addition to setting them in the tmux environment,
  both on CreateSession and Restart
- cfg/backends/claude.yaml adds CLAUDE_CONFIG_DIR to the sandbox env
  whitelist so landrun passes it through to the Claude process

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 11:49:02 +01:00
Levi Neely 065e4a3295
Add bulk-archive via inline Put notation to inbox and archive windows (#12)
* Add inline Put actions for sessions and tasks windows

Introduce a Put command to both the sessions list and tasks windows,
allowing inline edits via prefixed annotations in the body:

Sessions (cmd/Assist/main.go):
  - `- <id>`              Kill session
  - `~ <id>`              Stop session (graceful)
  - `@ <id> <alias>`      Set alias on session
  - `+ <backend> <path> [alias]`  Start new session

Tasks (cmd/Assist/main.go + internal/p9/beads.go):
  - `- [idx]`   Delete bead
  - `~ [idx]`   Claim bead as user
  - `^ [idx]`   Unclaim bead (clear assignee, reset to open)
  - `x [idx]`   Complete bead
  - `f [idx]`   Fail bead
  - `+ <title>` Create new bead with title pre-filled

Also adds `unclaim` ctl command to BeadsFS and helper functions:
claimBeadAsUser, unclaimBead, completeBead, failBead,
openNewBeadWindowWithTitle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add [Failed] [PendingReview] [PendingApproval] filters to tasks window

Extends the tasks window filter bar with three new status filters:

- [Failed]          closed beads whose close_reason != "completed"
- [PendingReview]   beads with status "pending_review"
- [PendingApproval] beads with status "pending_approval"

Implementation details:
- Add CloseReason field (json:"close_reason") to Bead struct so
  fail-vs-complete distinction is available after JSON decode.
- listBeadsWithFilter: add "failed" special case (closed beads with
  non-"completed" close_reason); "pending_review" and
  "pending_approval" fall through the existing status equality path.
- handleTasksWindow: wire Failed/PendingReview/PendingApproval cases
  to set statusFilter and refresh the list.
- refreshTasksWindowWithBeads: update filter bar header line.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add bulk-archive via inline Put notation to inbox and archive windows

In the inbox window, lines prefixed with "- <shortID>" are parsed on Put
and each matching message is archived (moved to completed). In the archive
window the same notation permanently deletes the message from the archive.

Adds: parseMailEdits, mailEdit type, deleteArchivedMessage in Assist;
DeleteFromCompleted in mailbox.Manager; "delete <msg-id>" command on
user/ctl in the p9 server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:58:37 +01:00
Levi Neely 5bba76d2b9 hotfixes, msg trace diagram generator 2026-02-23 12:20:46 +01:00
Levi Neely 45e495a975
Add requires_approval and requires_review flags to bead UI across all frontends (#10)
Implements bd-258: display and toggle of requires_approval / requires_review
boolean flags in all four AnviLLM frontends. Flags are backed by labels
(requires_approval, requires_review) on each bead, read from the labels
array in bead JSON and toggled via label/unlabel ctl commands.

- Acme: adds Labels/HasLabel to Bead struct; shows flags in frontmatter;
  updateBead parses and applies label/unlabel on Put
- TUI: showBead displays flags (green when set); edit dialog adds two
  checkboxes that toggle labels on save
- Web: detail view shows flag status with Set/Unset buttons; new
  toggleBeadFlag() function calls beads ctl API and refreshes
- Emacs: detail buffer shows flag lines; A/R keybindings invoke new
  anvillm-bead-toggle-approval and anvillm-bead-toggle-review commands

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 18:13:12 +01:00
Levi Neely db501cca26
Add approval/rejection flags and actions to tasks UI (#9)
* Add approval/rejection flags and actions to tasks UI

Adds visual flags for APPROVAL_REQUEST and REVIEW_REQUEST messages across
all UI frontends (Acme, TUI, web, Emacs), with one-click approve/reject
actions and inferred reply type mapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Auto-archive messages on approve or reject across all UIs

After an approval or rejection response is sent, the original inbox
message is now automatically completed/archived in all four frontends:

- Acme: handleReplyWindow gains an originalMsgID param; approve/reject
  windows pass the message ID so the original is archived on Send
- TUI: already archived via completeInboxMessage in approveMessage /
  rejectMessage — no change needed
- Web: approveCurrentMessage archives after reply succeeds; rejectCurrent-
  Message sets pendingArchiveId so the reply-form submit handler archives
  on send
- Emacs: anvillm-inbox-approve and anvillm-inbox-reject write "complete
  <id>" to user/ctl and refresh the inbox after sending the response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:38:23 +01:00
Levi Neely e1489a39fb fix: handle null sessions case in anvilwebgw
Initialize sessions slice as empty array instead of nil to ensure
JSON encoding returns [] instead of null when no sessions exist.
This prevents JavaScript iteration errors in the web frontend.
2026-02-22 11:14:57 +01:00
Levi Neely e9c78b11e0
Merge pull request #1 from lneely/anvilwebgw
Add anvilwebgw HTTP gateway service
2026-02-22 09:42:50 +01:00
Levi Neely 407b3732af Replace event queue with in-memory pub-sub event bus
Replaces the TTL-based event queue (internal/events) with a proper
in-memory pub-sub bus (internal/eventbus) backed by simonfxr/pubsub.

The agent/events 9P endpoint is now a streaming subscriber: clients
block on reads and receive one JSON-encoded event per read until they
disconnect. Each open(2) creates a per-connection subscription; clunk
and connection teardown cancel it automatically.

- internal/eventbus/bus.go: new package wrapping simonfxr/pubsub;
  provides Publish(agent, type, data) and Subscribe() -> (chan, cancel)
- internal/events/events.go: deleted
- internal/session/manager.go: SetEventQueue -> SetEventBus; all
  publish sites updated to use eventbus constants
- internal/p9/server.go: fid gains eventCh/eventUnsub fields; Topen
  subscribes, Tread blocks on channel, Tclunk/serve-defer cancel
- cmd/anvilsrv/main.go: wired to SetEventBus

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 09:38:14 +01:00
Levi Neely a28cf13cae Add anvilwebgw HTTP gateway service, simplify anvilweb
- New cmd/anvilwebgw: standalone HTTP gateway daemon with start/stop/fgstart/status
  subcommands, exposing all 9P-connected API endpoints on :8081
- cmd/anvilweb simplified to a plain static file server that reverse-proxies
  /api/* to anvilwebgw; removes all 9P connectivity
- Frontend error handling overhauled: replace alert() with styled dismissible
  error banner and inline container errors showing actual server response detail
- Fix CSS specificity bug that kept error banner always visible
- Fix nil slice JSON encoding (null vs []) for empty inbox/archive responses
- mkfile: add anvilwebgw build and clean targets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 09:01:23 +01:00
Levi Neely 9d0e9b7e42 Add ollama backend support
- Add ollama backend implementation using mcphost and ollie
- Add ollama.yaml sandbox configuration
- Update README with ollama installation and usage instructions
- Add ollama command to Assist, anvilmcp, and anvilsrv
- Add ANVILLM_OLLAMA_MODEL environment variable
- Hardcode ollama-mcp.json config path to ~/.config/anvillm/ollama-mcp.json
2026-02-21 21:03:55 +01:00
Levi Neely 5a212793c3 ui parity 2026-02-21 13:57:05 +01:00
Levi Neely dd6528bfee fix 2026-02-21 10:35:45 +01:00
Levi Neely 4257e6595d fix 2026-02-21 10:33:06 +01:00
Levi Neely 1aa3010200 Add status filter buttons to Tasks window
- Filter out closed tasks by default
- Add [Open] [InProgress] [Closed] filter buttons
- Maintain filter state during window session
- Position window at top after refresh
2026-02-21 10:31:20 +01:00
Levi Neely c6987a7962 Remove deprecated audit endpoint
- Remove audit endpoint routes from 9P filesystem
- Delete audit handler functions (readAuditLog, GetAuditLog)
- Remove audit package and all audit logging code
- Remove audit log viewer from TUI (anvillm)
- Remove audit log streaming from web UI (anvilweb)
- Update documentation to reference events system instead
- All audit functionality replaced by events system
2026-02-20 22:18:53 +01:00
Levi Neely 6a8bad003f remove beads thin wrapper, github-to-beads 2026-02-20 21:24:06 +01:00
Levi Neely bf8c0d7cdb improve bead id special case "fire-forget" prompt 2026-02-20 19:05:06 +01:00
Levi Neely 5854f95f9b Assist: Add Tasks window for beads task management
- Tasks window with sorted list, blocker count column, index for navigation
- View window with frontmatter (title, status, blockers), Put saves changes
- New window with blockers field for setting deps on create
- Hierarchical subtask IDs (bd-s2r.1) via parent-id parameter
- Blocks tag for quick dependency add via selection
- Remove tag for deleting beads via chord
- beads/ctl commands: new, update, delete, dep, undep
- beads/{id}/json includes blockers array
- Fixed parseQuotedArgs to preserve empty quoted strings
- Fixed escape sequence handling in descriptions
2026-02-20 10:13:53 +01:00
Levi Neely 9ebd239a95 Add beads task tracking integration via 9P filesystem
- Add beads dependency (steveyegge/beads)
- Create internal/beads/beads.go: Storage wrapper for beads operations
- Create internal/p9/beads.go: 9P filesystem handlers for beads
- Integrate beads into 9P server (shared across all namespaces)
- Add beads directory to 9P filesystem: /agent/beads/
- Support commands: init, new, claim, complete, fail, dep
- Add ANVILLM_BEADS_PATH env var for custom beads location
- Update IDEAS.md with multi-tracker import design (Jira, GitHub, GitLab, Linear)
- Beads provides persistent, crash-resilient task tracking for multi-agent workflows
2026-02-19 23:08:50 +01:00
Levi Neely 65be761262 Fix event system: wire state changes to OnStateChange and fix /events 9p read
- Wire all state changes in tmux session to use transitionToLocked (triggers OnStateChange)
  - Close() exited state
  - Refresh() stopped states (intentional stop, restart spam prevention, auto-restart failure, PID=0)
- Add event callbacks to mailbox manager for send/receive events
  - Callbacks fire when message removed from outbox (send) and delivered to inbox (receive)
  - Consistent with state change callback pattern
- Fix /events 9p read handler to respect offset/count
  - Prevents infinite read loop by properly signaling EOF
  - Uses readFile() pattern like /list for consistency
2026-02-19 20:18:55 +01:00
Levi Neely b2502b3f5a Inbox/Archive: session ID arg, short UUID display, timestamp column, sort by date 2026-02-19 16:54:18 +01:00
Levi Neely d3f1d67547 Add Archive window, UUID-based message lookup, fix backend column in list 2026-02-19 16:39:43 +01:00