o script: audit cleanup
- Merge readloop into read -l (loop mode) - Remove chatstream command (TUI uses 'o read chat' directly) - Rework ctl: o ctl <cmd> [session] [agent] — dispatches to session ctl for kill/pause/resume, agent ctl for the rest - Add trap EXIT to kill background statewait loop (fixes zombie) - Remove -1 compatibility flag from generate - Remove no-op bracketed paste bind from prompt REPL - Fix /i help text: 'inject prompt (mid-turn or queued)' - Update all help text to reflect current commands
This commit is contained in:
parent
49c93eab5f
commit
d1907adfae
158
data/scripts/o
158
data/scripts/o
|
|
@ -9,17 +9,14 @@
|
|||
# - No context set → path used as-is (root-relative)
|
||||
#
|
||||
# Subcommands:
|
||||
# read <path> Read a file
|
||||
# read <path> Read a file (-l to loop)
|
||||
# write <path> [data] Write to a file (args or stdin)
|
||||
# readloop <path> Read in a loop (re-reads after each return)
|
||||
# ls [path] List namespace entries
|
||||
# ctl <command> Send a control command (stop, compact, kill, ...)
|
||||
# prompt Interactive REPL for submitting prompts (requires agent)
|
||||
# tail Tail chat output (requires agent)
|
||||
# chatstream Stream chat output (requires agent)
|
||||
# tui Launch tmux TUI (requires agent)
|
||||
# env Print resolved session/agent environment
|
||||
# stop Interrupt running agent (requires agent)
|
||||
# kill Kill session (requires session)
|
||||
#
|
||||
# Environment:
|
||||
# session Session name (set via 'eval $(o env)')
|
||||
|
|
@ -161,23 +158,29 @@ require_agent() {
|
|||
echo "$a"
|
||||
}
|
||||
|
||||
agent_path() {
|
||||
local s a
|
||||
s=$(require_session) || return 1
|
||||
a=$(require_agent "$s") || return 1
|
||||
echo "session/$s/agent/$a"
|
||||
}
|
||||
|
||||
# ── Subcommands ──────────────────────────────────────────────────
|
||||
|
||||
cmd_read() {
|
||||
local loop=false
|
||||
while [[ "${1:-}" == -* ]]; do
|
||||
case "$1" in
|
||||
-l|--loop) loop=true; shift ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "usage: o read <path>" >&2
|
||||
echo "usage: o read [-l] <path>" >&2
|
||||
exit 1
|
||||
fi
|
||||
local path
|
||||
path=$(resolve_path "$1") || exit 1
|
||||
ollie-9p read "$path"
|
||||
if $loop; then
|
||||
while true; do
|
||||
ollie-9p read "$path" || break
|
||||
done
|
||||
else
|
||||
ollie-9p read "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_write() {
|
||||
|
|
@ -219,12 +222,8 @@ cmd_generate() {
|
|||
# One-shot generation via /generate (no session/agent needed)
|
||||
# Usage: o generate "prompt"
|
||||
# echo "prompt" | o generate
|
||||
# o generate -1 "prompt" (same as above)
|
||||
local prompt=""
|
||||
|
||||
# Handle -1 flag (ignored, for compatibility)
|
||||
[[ "${1:-}" == "-1" ]] && shift
|
||||
|
||||
if [[ $# -gt 0 ]]; then
|
||||
prompt="$*"
|
||||
else
|
||||
|
|
@ -270,28 +269,40 @@ cmd_route() {
|
|||
printf '%s' "$task" | ollie-9p rdwr route
|
||||
}
|
||||
|
||||
cmd_readloop() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "usage: o readloop <path>" >&2
|
||||
exit 1
|
||||
fi
|
||||
local file="$1"; shift
|
||||
local path
|
||||
path=$(resolve_path "$file") || exit 1
|
||||
while true; do
|
||||
ollie-9p read "$path" || break
|
||||
done
|
||||
}
|
||||
|
||||
cmd_ctl() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "usage: o ctl <command> [args...]" >&2
|
||||
echo " commands: stop, compact, kill, clear, model <m>, backend <b>, cwd <d>" >&2
|
||||
echo "usage: o ctl <command> [session] [agent]" >&2
|
||||
echo " With agent: stop, compact, clear, model <m>, backend <b>, cwd <d>" >&2
|
||||
echo " Session-only: kill, pause, resume" >&2
|
||||
exit 1
|
||||
fi
|
||||
local path
|
||||
path=$(agent_path) || exit 1
|
||||
echo "$*" | ollie-9p write "$path/ctl"
|
||||
local cmd="$1"; shift
|
||||
|
||||
# Resolve context from remaining args or env
|
||||
local s="${1:-${session:-}}"
|
||||
local a="${2:-${agent:-}}"
|
||||
|
||||
if [[ -z "$s" ]]; then
|
||||
echo "error: no session set" >&2
|
||||
echo " export session=<name> or o ctl <cmd> <session> [agent]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Session-level commands (no agent needed)
|
||||
case "$cmd" in
|
||||
kill|pause|resume)
|
||||
echo "$cmd" | ollie-9p write "session/$s/ctl"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
# Agent-level commands
|
||||
if [[ -z "$a" ]]; then
|
||||
echo "error: no agent set" >&2
|
||||
echo " export agent=<name> or o ctl <cmd> <session> <agent>" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$cmd" | ollie-9p write "session/$s/agent/$a/ctl"
|
||||
}
|
||||
|
||||
cmd_prompt() {
|
||||
|
|
@ -314,9 +325,6 @@ cmd_prompt() {
|
|||
|
||||
local buf="" line
|
||||
|
||||
# Enable bracketed paste mode - terminal sends \e[200~ before and \e[201~ after paste
|
||||
bind 'set enable-bracketed-paste on' 2>/dev/null
|
||||
|
||||
while true; do
|
||||
local prompt_str
|
||||
if [[ -z "$buf" ]]; then
|
||||
|
|
@ -365,7 +373,7 @@ cmd_prompt() {
|
|||
echo " /backend X — switch backend"
|
||||
echo " /cwd X — change working directory"
|
||||
echo " /quit /q — kill the tmux TUI"
|
||||
echo " /i — interrupt running agent"
|
||||
echo " /i <text> — inject prompt mid-turn"
|
||||
;;
|
||||
*) echo "unknown command: /$cmd (try /help)" ;;
|
||||
esac
|
||||
|
|
@ -395,20 +403,6 @@ cmd_prompt() {
|
|||
done
|
||||
}
|
||||
|
||||
cmd_chatstream() {
|
||||
local ctx s a
|
||||
ctx=$(resolve_context "$@") || exit 1
|
||||
s="${ctx%%|*}"
|
||||
a="${ctx##*|}"
|
||||
if [[ -z "$s" || -z "$a" ]]; then
|
||||
echo "error: session and agent are required" >&2
|
||||
echo " usage: o chatstream <session> <agent>" >&2
|
||||
echo " or: export session=<name> agent=<name>" >&2
|
||||
exit 1
|
||||
fi
|
||||
exec ollie-9p read "session/$s/agent/$a/chat"
|
||||
}
|
||||
|
||||
cmd_log() {
|
||||
local lines=1000
|
||||
local ctx s a
|
||||
|
|
@ -449,31 +443,6 @@ cmd_env() {
|
|||
fi
|
||||
}
|
||||
|
||||
cmd_stop() {
|
||||
local ctx s a
|
||||
ctx=$(resolve_context "$@") || exit 1
|
||||
s="${ctx%%|*}"
|
||||
a="${ctx##*|}"
|
||||
if [[ -z "$s" || -z "$a" ]]; then
|
||||
echo "error: session and agent are required" >&2
|
||||
echo " usage: o stop <session> <agent>" >&2
|
||||
echo " or: export session=<name> agent=<name>" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "stop" | ollie-9p write "session/$s/agent/$a/ctl"
|
||||
}
|
||||
|
||||
cmd_kill() {
|
||||
local s="${1:-${session:-}}"
|
||||
if [[ -z "$s" ]]; then
|
||||
echo "error: no session set" >&2
|
||||
echo " usage: o kill <session>" >&2
|
||||
echo " or: export session=<name>" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "kill" | ollie-9p write "session/$s/ctl"
|
||||
}
|
||||
|
||||
cmd_tui() {
|
||||
local tmux_session="${session:-}"
|
||||
local s a
|
||||
|
|
@ -523,7 +492,7 @@ cmd_tui() {
|
|||
# Pane 0: chat (top, 80%) - show last 1000 lines of log, then tail chat
|
||||
tmux -CC new-session -d -s "$tmux_session" -c "$HOME" \
|
||||
-e "session=$s" -e "agent=$a"
|
||||
tmux send-keys -t "$tmux_session" "o log -n 1000 | grep -v '\\[\\[\\[.*\\]\\]\\]' | grep -v '^\`\`\`'; o chatstream" Enter
|
||||
tmux send-keys -t "$tmux_session" "o log -n 1000 | grep -v '\\[\\[\\[.*\\]\\]\\]' | grep -v '^\`\`\`'; o read chat" Enter
|
||||
|
||||
# Pane 1: prompt REPL (bottom, 20% height)
|
||||
tmux split-window -t "$tmux_session" -v -l 20% \
|
||||
|
|
@ -544,10 +513,12 @@ cmd_tui() {
|
|||
paused) bg="colour245" ;; # gray
|
||||
*) bg="default" ;;
|
||||
esac
|
||||
tmux set-option -t "$tmux_session" status-right-style "fg=default,bg=$bg"
|
||||
tmux set-option -t "$tmux_session" status-right "$state | %H:%M"
|
||||
tmux set-option -t "$tmux_session" status-right-style "fg=default,bg=$bg" 2>/dev/null
|
||||
tmux set-option -t "$tmux_session" status-right "$state | %H:%M" 2>/dev/null
|
||||
done
|
||||
done &
|
||||
local bg_pid=$!
|
||||
trap "kill $bg_pid 2>/dev/null" EXIT
|
||||
|
||||
# Focus the prompt pane
|
||||
tmux select-pane -t "$tmux_session:0.1"
|
||||
|
|
@ -561,25 +532,21 @@ usage: o <command> [args...]
|
|||
|
||||
Path resolution:
|
||||
- Root paths (session/*, agents, models, etc.) → used as-is
|
||||
- Agent files (chat, state, prompt, etc.) → require $session + $agent
|
||||
- Agent files (chat, prompt, cfg, etc.) → require $session + $agent
|
||||
- Session files (env, ctl, name, etc.) → require $session
|
||||
|
||||
Commands:
|
||||
read <path> Read a file
|
||||
read [-l] <path> Read a file (-l: loop, re-read after each return)
|
||||
write <path> [data] Write to a file (args or stdin)
|
||||
readloop <path> Read in a loop (re-reads after return)
|
||||
ls [path] List namespace entries
|
||||
|
||||
generate <prompt> One-shot generation (no session needed)
|
||||
complete <json> Code completion (no session needed)
|
||||
route <task> Route task to best model (no session needed)
|
||||
|
||||
ctl <cmd> Send control command to agent
|
||||
stop Interrupt running agent
|
||||
kill Kill active session
|
||||
ctl <cmd> [s] [a] Send control command (session or agent level)
|
||||
|
||||
prompt Interactive multi-line prompt REPL
|
||||
chatstream Stream chat output
|
||||
log [-n N] Show last N lines of agent log (default 1000)
|
||||
tui Launch tmux layout
|
||||
tui exit Kill tmux TUI session
|
||||
|
|
@ -595,12 +562,13 @@ Examples:
|
|||
o ls # list at current context level
|
||||
o ls session # list all sessions
|
||||
o read models # read root-level file
|
||||
o read -l statewait # block-loop on state changes
|
||||
o read chat # stream chat (filtered text)
|
||||
o read chat.raw # stream chat (full markup)
|
||||
o generate "explain monads" # one-shot, no session
|
||||
o complete '{"file":"main.go","prefix":"func "}' # code completion
|
||||
o route "implement login" # route to best model
|
||||
o ctl stop # stop agent (uses $session/$agent)
|
||||
o ctl kill mysession # kill session by name
|
||||
export session=foo agent=bar # set context
|
||||
o read chat # read agent's chat
|
||||
o readloop statewait # blocks until agent state changes
|
||||
EOF
|
||||
}
|
||||
|
||||
|
|
@ -615,16 +583,12 @@ subcmd="$1"; shift
|
|||
case "$subcmd" in
|
||||
read) cmd_read "$@" ;;
|
||||
write) cmd_write "$@" ;;
|
||||
readloop) cmd_readloop "$@" ;;
|
||||
ls) cmd_ls "$@" ;;
|
||||
generate) cmd_generate "$@" ;;
|
||||
complete) cmd_complete "$@" ;;
|
||||
route) cmd_route "$@" ;;
|
||||
ctl) cmd_ctl "$@" ;;
|
||||
stop) cmd_stop "$@" ;;
|
||||
kill) cmd_kill "$@" ;;
|
||||
prompt) cmd_prompt "$@" ;;
|
||||
chatstream) cmd_chatstream "$@" ;;
|
||||
log) cmd_log "$@" ;;
|
||||
tui) cmd_tui "$@" ;;
|
||||
env) cmd_env "$@" ;;
|
||||
|
|
|
|||
Loading…
Reference in New Issue