Commit Graph

86 Commits

Author SHA1 Message Date
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
Levi Neely 840453f2cc Format read_inbox output like 9p-read-inbox
- Parse JSON and format as: [Message from X] / Type / Subject / Body
- Makes it clear who the sender is for replying
- Matches original 9p-read-inbox behavior
2026-02-18 22:14:01 +01:00
Levi Neely 1139172a7e Return actual error messages from 9p commands
- Capture stderr/stdout from 9p write failures
- Return helpful error messages (e.g., list of valid message types)
- Allows agents to retry with correct values
2026-02-18 22:03:50 +01:00
Levi Neely 3f5c4da1e7 Make read_inbox auto-complete messages like 9p-read-inbox
- Read only first message (not all messages)
- Automatically mark message as complete after reading
- Matches behavior of original 9p-read-inbox script
2026-02-18 21:56:08 +01:00
Levi Neely 199595416f Handle notifications/initialized properly
- Don't return error for notification methods
- Notifications don't expect responses per JSON-RPC spec
2026-02-18 21:43:30 +01:00
Levi Neely 19fb829d4e Add stdout flush for MCP protocol reliability
- Flush stdout after each JSON-RPC response
- Ensures responses are immediately available to MCP clients
2026-02-18 21:42:32 +01:00
Levi Neely f6a3de17ae Add set_state tool to anvilmcp
- Allows setting agent state via MCP (idle, running, stopped, etc.)
- Validates state values via enum in schema
- Enables agent hooks to update their own state
2026-02-18 19:54:36 +01:00
Levi Neely b0c069bfa4 Add anvilmcp: MCP server for 9p agent communication
- Implements MCP protocol server that translates to 9p operations
- Three tools: read_inbox, send_message, list_sessions
- Uses plan9port 9p client for filesystem operations
- Debug logging to stderr, JSON-RPC on stdout
- Enables MCP clients to interact with anvilsrv daemon
2026-02-18 19:52:37 +01:00
Levi Neely 4b87a7795f Assist: reuse existing terminal for tmux attach
- Check for existing tmux clients before launching new terminal
- Use 'tmux switch-client' to reuse existing terminal window
- Fall back to new terminal only when no client is attached
2026-02-18 16:31:21 +01:00
Levi Neely b8013b1b87 Assist: middle-click session ID attaches to tmux
- Middle-click on session ID without selection now attaches to tmux session
- Preserves existing fire-and-forget prompt behavior when text is selected
- Same functionality as 'Attach {session-id}' command
2026-02-18 16:26:21 +01:00
Levi Neely 937ad83e97 Remove deprecated endpoints and fix mailbox auto-completion
- Fix PROMPT_RESPONSE messages not auto-completing
- Remove deprecated message types (LogInfo, LogError, StatusUpdate)
- Remove entire chat log system (replaced by audit log)
- Migrate user prompts to mailbox system in main.go
- Remove {id}/in and {id}/out 9P endpoints
- Only mail processor uses sess.Send() directly
- Fix file index constants after removing in/out files
- Remove unused SendCtl function
2026-02-17 23:06:07 +01:00
Levi Neely b199fb23dc Remove Sandbox configuration window from Assist
- Remove Sandbox button from main window tag
- Remove Sandbox case handler and related functions
- Remove sandbox package import
- Delete internal/ui/sandbox.go

The Sandbox window is no longer needed as sandbox configuration
has been split into layered configuration (global, backends, roles, tools).
2026-02-17 22:18:02 +01:00
Levi Neely 314d347e76 Add centralized audit log system
- Created internal/audit package for centralized logging
- Replaced per-session log files with single agent/audit file
- Updated all UIs (TUI, web, Emacs) to use centralized audit log
- Modified mailbox manager to log all message deliveries with aliases
- Updated Alog script to stream centralized audit log
- Removed session-specific log streaming in favor of global audit log
2026-02-17 22:07:39 +01:00
Levi Neely ff2bd372c1 improve send message api 2026-02-17 18:20:01 +01:00
Levi Neely a069a98ccc Add Archive button to Acme inbox message windows
- Added Archive to message window tag line
- Archive writes 'complete <msg-id>' to user/ctl
- Window closes after successful archive
- Added ID field to Message struct
- Added error handling for archive failures
2026-02-17 17:28:52 +01:00