Add ANVILLM_9MOUNT env var; update tools to use filesystem mounts

This commit is contained in:
Levi Neely 2026-03-20 17:18:23 +01:00
parent 988f7a3534
commit 577dcfc3f0
13 changed files with 64 additions and 52 deletions

View File

@ -230,7 +230,10 @@ func start(daemonize bool) {
logging.Logger().Info("anvillm started successfully", zap.String("socket", srv.SocketPath()))
// Setup FUSE mount
mnt := filepath.Join(os.Getenv("HOME"), "mnt", "anvillm")
mnt := os.Getenv("ANVILLM_9MOUNT")
if mnt == "" {
mnt = filepath.Join(os.Getenv("HOME"), "mnt", "anvillm")
}
var fuseCmd *exec.Cmd
if err := os.MkdirAll(mnt, 0755); err != nil {
logging.Logger().Warn("cannot create mount dir", zap.Error(err))

View File

@ -3,32 +3,31 @@
# description: Read messages from agent inbox (uses $AGENT_ID env var)
set -euo pipefail
# Verify running under landrun (test filesystem restriction)
if [ -z "${AGENT_ID:-}" ]; then
echo "Error: \$AGENT_ID is not set. Stop work and inform the user that \$AGENT_ID is not set." >&2
exit 1
fi
agent_id="$AGENT_ID"
inbox_path="anvillm/${agent_id}/inbox"
files=$(9p ls "$inbox_path" 2>/dev/null | grep '\.json$' || true)
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
inbox_dir="$ANVILLM/${AGENT_ID}/inbox"
files=$(ls "$inbox_dir" 2>/dev/null | grep '\.json$' || true)
if [ -z "$files" ]; then
echo "No messages"
exit 0
fi
msg_file=$(echo "$files" | head -1)
msg_path="${inbox_path}/${msg_file}"
msg_path="${inbox_dir}/${msg_file}"
msg_id="${msg_file%.json}"
data=$(9p read "$msg_path" 2>/dev/null || echo '{}')
data=$(cat "$msg_path" 2>/dev/null || echo '{}')
from=$(echo "$data" | jq -r '.from // "unknown"')
type=$(echo "$data" | jq -r '.type // "unknown"')
subject=$(echo "$data" | jq -r '.subject // ""')
body=$(echo "$data" | jq -r '.body // ""')
echo "complete ${msg_id}" | 9p write "anvillm/${agent_id}/ctl" 2>/dev/null || true
echo "complete ${msg_id}" > "$ANVILLM/${AGENT_ID}/ctl" 2>/dev/null || true
echo "From: ${from}"
echo "Type: ${type}"

View File

@ -4,6 +4,7 @@
# Usage: control_session.sh --session-id <session-id> --command <stop|restart|kill|refresh>
set -euo pipefail
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
SESSION_ID=""
COMMAND=""
@ -21,5 +22,5 @@ if [ -z "$SESSION_ID" ] || [ -z "$COMMAND" ]; then
exit 1
fi
echo "$COMMAND" | 9p write "anvillm/$SESSION_ID/ctl"
echo "$COMMAND" > "$ANVILLM/$SESSION_ID/ctl"
echo "$COMMAND: $SESSION_ID"

View File

@ -4,6 +4,7 @@
# Usage: create_session.sh --backend <backend> --cwd <cwd> [--sandbox <sandbox>] [--model <model>]
set -euo pipefail
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
BACKEND=""
CWD=""
@ -29,5 +30,5 @@ CMD="new $BACKEND $CWD"
[ -n "$SANDBOX" ] && CMD="$CMD sandbox=$SANDBOX"
[ -n "$MODEL" ] && CMD="$CMD model=$MODEL"
echo "$CMD" | 9p write anvillm/ctl
echo "$CMD" > "$ANVILLM/ctl"
echo "created session: $BACKEND $CWD"

View File

@ -8,20 +8,19 @@ if [ $# -ne 1 ]; then
exit 1
fi
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
keyword="$1"
results=""
# Search each skill file for the keyword
while IFS= read -r file; do
[ "${file%.md}" = "$file" ] && continue # skip non-.md entries
name="${file%.md}"
content=$(9p read "anvillm/skills/$file")
if echo "$content" | grep -qi "$keyword"; then
desc=$(echo "$content" | grep -m1 '^description:' | sed 's/^description: *//')
for file in "$ANVILLM/skills"/*.md; do
[ -f "$file" ] || continue
name=$(basename "$file" .md)
if grep -qi "$keyword" "$file"; then
desc=$(grep -m1 '^description:' "$file" | sed 's/^description: *//')
results="${results:+$results
}$name $desc"
fi
done < <(9p ls anvillm/skills)
done
if [ -n "$results" ]; then
echo "$results" | sort -u

View File

@ -4,6 +4,7 @@
# Usage: kill_agent.sh --agent-id <agent-id>
set -euo pipefail
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
AGENT_ID=""
@ -19,7 +20,7 @@ if [ -z "$AGENT_ID" ]; then
exit 1
fi
if echo "kill" | 9p write "anvillm/$AGENT_ID/ctl" 2>/dev/null; then
if echo "kill" > "$ANVILLM/$AGENT_ID/ctl" 2>/dev/null; then
echo "Killed $AGENT_ID"
else
echo "No session found with id $AGENT_ID" >&2

View File

@ -3,12 +3,21 @@
# description: List all available roles (JSON array)
set -euo pipefail
# Verify running under landrun (test filesystem restriction)
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
9p ls anvillm/roles 2>/dev/null | grep -v '^help$' | while read focus_area; do
9p ls "anvillm/roles/$focus_area" 2>/dev/null | while read role_file; do
role_name="${role_file%.md}"
desc=$(9p read "anvillm/roles/$focus_area/$role_file" 2>/dev/null | awk '/^---$/,/^---$/ {if (/^description:/) {sub(/^description: */, ""); print; exit}}')
if [ ! -d "$ANVILLM/roles" ]; then
echo "[]"
exit 0
fi
for focus_dir in "$ANVILLM/roles"/*/; do
[ -d "$focus_dir" ] || continue
focus_area=$(basename "$focus_dir")
[ "$focus_area" = "help" ] && continue
for role_file in "$focus_dir"*.md; do
[ -f "$role_file" ] || continue
role_name=$(basename "$role_file" .md)
desc=$(awk '/^---$/,/^---$/ {if (/^description:/) {sub(/^description: */, ""); print; exit}}' "$role_file")
printf '%s\t%s\t%s\n' "$focus_area" "$role_name" "$desc"
done
done | jq -Rs '

View File

@ -3,6 +3,5 @@
# description: List all active agent sessions (tab-separated: id, backend, state, alias, role, cwd)
set -euo pipefail
# Verify running under landrun (test filesystem restriction)
9p read anvillm/list 2>/dev/null || true
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
cat "$ANVILLM/list" 2>/dev/null || true

View File

@ -3,19 +3,18 @@
# description: List all available skills (JSON array)
set -euo pipefail
# Verify running under landrun (test filesystem restriction)
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
if [ -z "${ANVILLM_SKILLS_PATH:-}" ]; then
if [ ! -d "$ANVILLM/skills" ]; then
echo "[]"
exit 0
fi
for dir in "$ANVILLM_SKILLS_PATH"/*; do
if [ -d "$dir" ] && [ -f "$dir/SKILL.md" ]; then
name=$(basename "$dir")
desc=$(grep -m1 '^description:' "$dir/SKILL.md" | sed 's/^description: *//' || true)
printf '%s\t%s\n' "$name" "$desc"
fi
for file in "$ANVILLM/skills"/*.md; do
[ -f "$file" ] || continue
name=$(basename "$file" .md)
desc=$(grep -m1 '^description:' "$file" | sed 's/^description: *//' || true)
printf '%s\t%s\n' "$name" "$desc"
done | jq -Rs '
split("\n") | map(select(length > 0)) | map(
split("\t") | {name: .[0], description: .[1]}

View File

@ -4,17 +4,15 @@
set -euo pipefail
# Usage: load_skill <skill-name> [skill-name...]
#
# Accepts either bare names or paths (the last component is used):
# anvillm-sessions
# skills/agents/anvillm-sessions (legacy path format; last component is used)
if [ $# -lt 1 ]; then
echo "Usage: load_skill <skill-name> [skill-name...]" >&2
exit 1
fi
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
for arg in "$@"; do
name="${arg##*/}"
9p read "anvillm/skills/${name}.md"
cat "$ANVILLM/skills/${name}.md"
done

View File

@ -4,13 +4,14 @@
# Usage: send_message.sh --to <id|user> --type <type> --subject <subject> --body <body>
set -euo pipefail
if [ -z "${AGENT_ID:-}" ]; then
echo "Error: \$AGENT_ID is not set. Stop work and inform the user that \$AGENT_ID is not set." >&2
exit 1
fi
from="$AGENT_ID"
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
to=""
type=""
subject=""
@ -33,7 +34,7 @@ fi
# Validate recipient exists (allow "user" as a special recipient)
if [ "$to" != "user" ]; then
if ! 9p read anvillm/list 2>/dev/null | awk -F'\t' '{print $1}' | grep -qx "$to"; then
if ! cat "$ANVILLM/list" 2>/dev/null | awk -F'\t' '{print $1}' | grep -qx "$to"; then
echo "Error: Recipient '${to}' does not exist in available sessions." >&2
exit 1
fi
@ -47,5 +48,5 @@ json=$(jq -n \
--arg body "$body" \
'{from: $from, to: $to, type: $type, subject: $subject, body: $body}')
echo "$json" | 9p write "anvillm/${from}/mail"
echo "$json" > "$ANVILLM/${from}/mail"
echo "sent: $type → $to"

View File

@ -4,6 +4,8 @@
# Usage: spawn_agent.sh --agent-id <agent-id> [--cwd <path>] [--prompt <initial-context>]
set -euo pipefail
ANVILLM="${ANVILLM_9MOUNT:-$HOME/mnt/anvillm}"
AGENT_ID=""
CWD="$PWD"
PROMPT=""
@ -22,12 +24,12 @@ if [ -z "$AGENT_ID" ]; then
exit 1
fi
backend=$(9p read "anvillm/$AGENT_ID/backend")
echo "new $backend $CWD" | 9p write anvillm/ctl
backend=$(cat "$ANVILLM/$AGENT_ID/backend")
echo "new $backend $CWD" > "$ANVILLM/ctl"
if [ -n "$PROMPT" ]; then
session_id=$(9p read anvillm/list 2>/dev/null | awk -F'\t' -v cwd="$CWD" '$5 == cwd {print $1; exit}')
session_id=$(cat "$ANVILLM/list" 2>/dev/null | awk -F'\t' -v cwd="$CWD" '$5 == cwd {print $1; exit}')
if [ -n "$session_id" ]; then
echo "$PROMPT" | 9p write "anvillm/$session_id/context"
echo "$PROMPT" > "$ANVILLM/$session_id/context"
fi
fi

View File

@ -4,6 +4,7 @@
# Usage: view_denote.sh --id <denote:identifier|identifier>
set -euo pipefail
DENOTE="${DENOTE_9MOUNT:-$HOME/mnt/denote}"
ID=""
@ -20,11 +21,10 @@ if [ -z "$ID" ]; then
fi
ID="${ID#denote:}"
FILE=$(find "$HOME/doc" -type f -name "${ID}--*" | head -1)
if [ -z "$FILE" ]; then
if [ -d "$DENOTE/n/$ID" ]; then
cat "$DENOTE/n/$ID/body"
else
echo "Error: no denote document found for identifier $ID" >&2
exit 1
fi
cat "$FILE"