toys: rename ollie.sh→osh, oq restored
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d1f4b8eaef
commit
4b2927067a
124
toys/ollie.sh
124
toys/ollie.sh
|
|
@ -1,124 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# ollie.sh: a simplified, fully-functional chat interface for ollie AI agents.
|
|
||||||
set -o history
|
|
||||||
|
|
||||||
MOUNT=${OLLIE_9MOUNT:-$HOME/mnt/ollie}
|
|
||||||
LAST=$HOME/.config/ollie/last-session
|
|
||||||
|
|
||||||
# load_session <dir> → prints session ID for that dir, or nothing
|
|
||||||
load_session() {
|
|
||||||
awk -F'\t' -v d="$1" 'NF==2 && $1==d {print $2; exit}' "$LAST" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# save_session <dir> <id> → upserts {dir}\t{id} in $LAST
|
|
||||||
save_session() {
|
|
||||||
local dir="$1" id="$2" tmp
|
|
||||||
mkdir -p "$(dirname "$LAST")"
|
|
||||||
tmp=$(mktemp)
|
|
||||||
awk -F'\t' -v d="$dir" 'NF==2 && $1!=d' "$LAST" 2>/dev/null > "$tmp" || true
|
|
||||||
printf '%s\t%s\n' "$dir" "$id" >> "$tmp"
|
|
||||||
mv "$tmp" "$LAST"
|
|
||||||
}
|
|
||||||
|
|
||||||
die() { printf 'error: %s\n' "$*" >&2; exit 1; }
|
|
||||||
is_idle() { [ "$(tr -d '[:space:]' < "$S/state" 2>/dev/null)" = "idle" ]; }
|
|
||||||
drain() {
|
|
||||||
local n
|
|
||||||
n=$(wc -c < "$S/chat" 2>/dev/null || echo 0)
|
|
||||||
[ "$n" -gt "$chat_off" ] && tail -c "+$((chat_off+1))" "$S/chat" | head -c "$((n-chat_off))"
|
|
||||||
chat_off=$n
|
|
||||||
}
|
|
||||||
|
|
||||||
# Parse flags
|
|
||||||
new=0; resume=0; id_flag=
|
|
||||||
backend=; model=; agent=; cwd=
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case $1 in
|
|
||||||
-new) new=1 ;;
|
|
||||||
-resume) resume=1 ;;
|
|
||||||
-session) id_flag=$2; shift ;;
|
|
||||||
-backend) backend=$2; shift ;;
|
|
||||||
-model) model=$2; shift ;;
|
|
||||||
-agent) agent=$2; shift ;;
|
|
||||||
-cwd) cwd=$2; shift ;;
|
|
||||||
*) die "unknown flag: $1" ;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
# Build "new" ctl command with opts
|
|
||||||
new_cmd() {
|
|
||||||
local cmd=new
|
|
||||||
[ -n "$backend" ] && cmd="$cmd backend=$backend"
|
|
||||||
[ -n "$model" ] && cmd="$cmd model=$model"
|
|
||||||
[ -n "$agent" ] && cmd="$cmd agent=$agent"
|
|
||||||
cmd="$cmd cwd=${cwd:-$(pwd)}"
|
|
||||||
printf '%s\n' "$cmd"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create a fresh session, sets $id
|
|
||||||
create_session() {
|
|
||||||
local before d deadline
|
|
||||||
before=$(ls "$MOUNT/s" 2>/dev/null)
|
|
||||||
new_cmd > "$MOUNT/ctl" || die "write ctl"
|
|
||||||
deadline=$(($(date +%s) + 5))
|
|
||||||
while [ "$(date +%s)" -lt "$deadline" ]; do
|
|
||||||
for d in $(ls "$MOUNT/s" 2>/dev/null); do
|
|
||||||
printf '%s\n' "$before" | grep -qxF "$d" || { id=$d; return; }
|
|
||||||
done
|
|
||||||
sleep 0.05
|
|
||||||
done
|
|
||||||
die "timeout waiting for new session"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Resolve session
|
|
||||||
_dir=${cwd:-$(pwd)}
|
|
||||||
if [ -n "$id_flag" ]; then
|
|
||||||
[ -d "$MOUNT/s/$id_flag" ] || die "session not found: $id_flag"
|
|
||||||
id=$id_flag; printf 'session: %s (resumed)\n' "$id" >&2
|
|
||||||
elif [ "$resume" = 1 ]; then
|
|
||||||
id=$(load_session "$_dir")
|
|
||||||
[ -n "$id" ] && [ -d "$MOUNT/s/$id" ] || die "no resumable session for $_dir"
|
|
||||||
printf 'session: %s (resumed)\n' "$id" >&2
|
|
||||||
elif [ "$new" = 1 ]; then
|
|
||||||
create_session
|
|
||||||
save_session "$_dir" "$id"
|
|
||||||
printf 'session: %s\n' "$id" >&2
|
|
||||||
else
|
|
||||||
id=$(load_session "$_dir")
|
|
||||||
if [ -n "$id" ] && [ -d "$MOUNT/s/$id" ]; then
|
|
||||||
printf 'session: %s (resumed)\n' "$id" >&2
|
|
||||||
else
|
|
||||||
create_session
|
|
||||||
save_session "$_dir" "$id"
|
|
||||||
printf 'session: %s\n' "$id" >&2
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
S=$MOUNT/s/$id
|
|
||||||
chat_off=$(wc -c < "$S/chat" 2>/dev/null || echo 0)
|
|
||||||
|
|
||||||
trap '
|
|
||||||
[ "$(tr -d "[:space:]" < "$S/state" 2>/dev/null)" = "idle" ] && exit
|
|
||||||
printf "\n" >&2; printf "stop\n" > "$S/ctl"
|
|
||||||
' INT
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
printf '> '
|
|
||||||
IFS= read -re input || break
|
|
||||||
[ -z "$input" ] && continue
|
|
||||||
history -s "$input"
|
|
||||||
case "$input" in
|
|
||||||
/kill) printf 'kill %s\n' "$id" > "$MOUNT/ctl"; break ;;
|
|
||||||
"/q "*) printf '%s\n' "${input#/q }" > "$S/enqueue"
|
|
||||||
printf 'queued\n' >&2; continue ;;
|
|
||||||
/*) printf '%s\n' "$input" > "$S/ctl" ;;
|
|
||||||
*) printf '%s' "$input" > "$S/prompt" || { printf 'submit failed\n' >&2; continue; } ;;
|
|
||||||
esac
|
|
||||||
sleep 0.15
|
|
||||||
while true; do
|
|
||||||
drain
|
|
||||||
is_idle && { drain; printf '\n'; break; }
|
|
||||||
sleep 0.05
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# oq: non-interactive ollie query via b/ namespace.
|
||||||
|
#
|
||||||
|
# Usage: oq [flags] [prompt...]
|
||||||
|
# echo "prompt" | oq [flags]
|
||||||
|
#
|
||||||
|
# Flags:
|
||||||
|
# -name base name for the job(s); suffixed with -0, -1, ...
|
||||||
|
# -cwd working directory (default: pwd)
|
||||||
|
# -agent agent config name
|
||||||
|
# -backend backend override
|
||||||
|
# -model model override
|
||||||
|
# -output output format hint (e.g. json)
|
||||||
|
# -parallel run the same prompt N times in parallel (default: 1)
|
||||||
|
# -keep do not remove job(s) after printing result
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
MOUNT=${OLLIE_9MOUNT:-$HOME/mnt/ollie}
|
||||||
|
|
||||||
|
die() { printf 'oq: %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
name=; cwd=; agent=; backend=; model=; output=; parallel=1; keep=0
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case $1 in
|
||||||
|
-name) name=$2; shift ;;
|
||||||
|
-cwd) cwd=$2; shift ;;
|
||||||
|
-agent) agent=$2; shift ;;
|
||||||
|
-backend) backend=$2; shift ;;
|
||||||
|
-model) model=$2; shift ;;
|
||||||
|
-output) output=$2; shift ;;
|
||||||
|
-parallel) parallel=$2; shift ;;
|
||||||
|
-keep) keep=1 ;;
|
||||||
|
--) shift; break ;;
|
||||||
|
-*) die "unknown flag: $1" ;;
|
||||||
|
*) break ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Prompt from remaining args or stdin.
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
prompt="$*"
|
||||||
|
elif ! [ -t 0 ]; then
|
||||||
|
prompt=$(cat)
|
||||||
|
else
|
||||||
|
die "prompt required: pass as arguments or pipe via stdin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z "$prompt" ] && die "empty prompt"
|
||||||
|
|
||||||
|
cwd=${cwd:-$(pwd)}
|
||||||
|
[ -z "$name" ] && name=$(date +%s%N)-$$
|
||||||
|
|
||||||
|
{
|
||||||
|
printf 'name=%s\n' "$name"
|
||||||
|
printf 'cwd=%s\n' "$cwd"
|
||||||
|
[ -n "$agent" ] && printf 'agent=%s\n' "$agent"
|
||||||
|
[ -n "$backend" ] && printf 'backend=%s\n' "$backend"
|
||||||
|
[ -n "$model" ] && printf 'model=%s\n' "$model"
|
||||||
|
[ -n "$output" ] && printf 'output=%s\n' "$output"
|
||||||
|
printf 'parallel=%s\n' "$parallel"
|
||||||
|
printf -- '---\n'
|
||||||
|
printf '%s\n' "$prompt"
|
||||||
|
} > "$MOUNT/b/new" || die "failed to submit job"
|
||||||
|
|
||||||
|
rc=0
|
||||||
|
for i in $(seq 0 $((parallel - 1))); do
|
||||||
|
id="${name}-${i}"
|
||||||
|
B="$MOUNT/b/$id"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
status=$(tr -d '[:space:]' < "$B/status" 2>/dev/null) || { sleep 0.05; continue; }
|
||||||
|
case "$status" in
|
||||||
|
done*) break ;;
|
||||||
|
failed*) rc=1; break ;;
|
||||||
|
*) sleep 0.05 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[ "$parallel" -gt 1 ] && printf '=== %s ===\n' "$id"
|
||||||
|
cat "$B/result" 2>/dev/null
|
||||||
|
|
||||||
|
[ "$keep" -eq 0 ] && rm -r "$B" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $rc
|
||||||
168
toys/osh
168
toys/osh
|
|
@ -1,88 +1,124 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# osh: non-interactive ollie query via b/ namespace.
|
# ollie.sh: a simplified, fully-functional chat interface for ollie AI agents.
|
||||||
#
|
set -o history
|
||||||
# Usage: osh [flags] [prompt...]
|
|
||||||
# echo "prompt" | osh [flags]
|
|
||||||
#
|
|
||||||
# Flags:
|
|
||||||
# -name base name for the job(s); suffixed with -0, -1, ...
|
|
||||||
# -cwd working directory (default: pwd)
|
|
||||||
# -agent agent config name
|
|
||||||
# -backend backend override
|
|
||||||
# -model model override
|
|
||||||
# -output output format hint (e.g. json)
|
|
||||||
# -parallel run the same prompt N times in parallel (default: 1)
|
|
||||||
# -keep do not remove job(s) after printing result
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
MOUNT=${OLLIE_9MOUNT:-$HOME/mnt/ollie}
|
MOUNT=${OLLIE_9MOUNT:-$HOME/mnt/ollie}
|
||||||
|
LAST=$HOME/.config/ollie/last-session
|
||||||
|
|
||||||
die() { printf 'osh: %s\n' "$*" >&2; exit 1; }
|
# load_session <dir> → prints session ID for that dir, or nothing
|
||||||
|
load_session() {
|
||||||
|
awk -F'\t' -v d="$1" 'NF==2 && $1==d {print $2; exit}' "$LAST" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
name=; cwd=; agent=; backend=; model=; output=; parallel=1; keep=0
|
# save_session <dir> <id> → upserts {dir}\t{id} in $LAST
|
||||||
|
save_session() {
|
||||||
|
local dir="$1" id="$2" tmp
|
||||||
|
mkdir -p "$(dirname "$LAST")"
|
||||||
|
tmp=$(mktemp)
|
||||||
|
awk -F'\t' -v d="$dir" 'NF==2 && $1!=d' "$LAST" 2>/dev/null > "$tmp" || true
|
||||||
|
printf '%s\t%s\n' "$dir" "$id" >> "$tmp"
|
||||||
|
mv "$tmp" "$LAST"
|
||||||
|
}
|
||||||
|
|
||||||
|
die() { printf 'error: %s\n' "$*" >&2; exit 1; }
|
||||||
|
is_idle() { [ "$(tr -d '[:space:]' < "$S/state" 2>/dev/null)" = "idle" ]; }
|
||||||
|
drain() {
|
||||||
|
local n
|
||||||
|
n=$(wc -c < "$S/chat" 2>/dev/null || echo 0)
|
||||||
|
[ "$n" -gt "$chat_off" ] && tail -c "+$((chat_off+1))" "$S/chat" | head -c "$((n-chat_off))"
|
||||||
|
chat_off=$n
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse flags
|
||||||
|
new=0; resume=0; id_flag=
|
||||||
|
backend=; model=; agent=; cwd=
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
-name) name=$2; shift ;;
|
-new) new=1 ;;
|
||||||
-cwd) cwd=$2; shift ;;
|
-resume) resume=1 ;;
|
||||||
-agent) agent=$2; shift ;;
|
-session) id_flag=$2; shift ;;
|
||||||
-backend) backend=$2; shift ;;
|
-backend) backend=$2; shift ;;
|
||||||
-model) model=$2; shift ;;
|
-model) model=$2; shift ;;
|
||||||
-output) output=$2; shift ;;
|
-agent) agent=$2; shift ;;
|
||||||
-parallel) parallel=$2; shift ;;
|
-cwd) cwd=$2; shift ;;
|
||||||
-keep) keep=1 ;;
|
*) die "unknown flag: $1" ;;
|
||||||
--) shift; break ;;
|
|
||||||
-*) die "unknown flag: $1" ;;
|
|
||||||
*) break ;;
|
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
# Prompt from remaining args or stdin.
|
# Build "new" ctl command with opts
|
||||||
if [ $# -gt 0 ]; then
|
new_cmd() {
|
||||||
prompt="$*"
|
local cmd=new
|
||||||
elif ! [ -t 0 ]; then
|
[ -n "$backend" ] && cmd="$cmd backend=$backend"
|
||||||
prompt=$(cat)
|
[ -n "$model" ] && cmd="$cmd model=$model"
|
||||||
|
[ -n "$agent" ] && cmd="$cmd agent=$agent"
|
||||||
|
cmd="$cmd cwd=${cwd:-$(pwd)}"
|
||||||
|
printf '%s\n' "$cmd"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a fresh session, sets $id
|
||||||
|
create_session() {
|
||||||
|
local before d deadline
|
||||||
|
before=$(ls "$MOUNT/s" 2>/dev/null)
|
||||||
|
new_cmd > "$MOUNT/ctl" || die "write ctl"
|
||||||
|
deadline=$(($(date +%s) + 5))
|
||||||
|
while [ "$(date +%s)" -lt "$deadline" ]; do
|
||||||
|
for d in $(ls "$MOUNT/s" 2>/dev/null); do
|
||||||
|
printf '%s\n' "$before" | grep -qxF "$d" || { id=$d; return; }
|
||||||
|
done
|
||||||
|
sleep 0.05
|
||||||
|
done
|
||||||
|
die "timeout waiting for new session"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Resolve session
|
||||||
|
_dir=${cwd:-$(pwd)}
|
||||||
|
if [ -n "$id_flag" ]; then
|
||||||
|
[ -d "$MOUNT/s/$id_flag" ] || die "session not found: $id_flag"
|
||||||
|
id=$id_flag; printf 'session: %s (resumed)\n' "$id" >&2
|
||||||
|
elif [ "$resume" = 1 ]; then
|
||||||
|
id=$(load_session "$_dir")
|
||||||
|
[ -n "$id" ] && [ -d "$MOUNT/s/$id" ] || die "no resumable session for $_dir"
|
||||||
|
printf 'session: %s (resumed)\n' "$id" >&2
|
||||||
|
elif [ "$new" = 1 ]; then
|
||||||
|
create_session
|
||||||
|
save_session "$_dir" "$id"
|
||||||
|
printf 'session: %s\n' "$id" >&2
|
||||||
else
|
else
|
||||||
die "prompt required: pass as arguments or pipe via stdin"
|
id=$(load_session "$_dir")
|
||||||
|
if [ -n "$id" ] && [ -d "$MOUNT/s/$id" ]; then
|
||||||
|
printf 'session: %s (resumed)\n' "$id" >&2
|
||||||
|
else
|
||||||
|
create_session
|
||||||
|
save_session "$_dir" "$id"
|
||||||
|
printf 'session: %s\n' "$id" >&2
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -z "$prompt" ] && die "empty prompt"
|
S=$MOUNT/s/$id
|
||||||
|
chat_off=$(wc -c < "$S/chat" 2>/dev/null || echo 0)
|
||||||
|
|
||||||
cwd=${cwd:-$(pwd)}
|
trap '
|
||||||
[ -z "$name" ] && name=$(date +%s%N)-$$
|
[ "$(tr -d "[:space:]" < "$S/state" 2>/dev/null)" = "idle" ] && exit
|
||||||
|
printf "\n" >&2; printf "stop\n" > "$S/ctl"
|
||||||
|
' INT
|
||||||
|
|
||||||
{
|
while true; do
|
||||||
printf 'name=%s\n' "$name"
|
printf '> '
|
||||||
printf 'cwd=%s\n' "$cwd"
|
IFS= read -re input || break
|
||||||
[ -n "$agent" ] && printf 'agent=%s\n' "$agent"
|
[ -z "$input" ] && continue
|
||||||
[ -n "$backend" ] && printf 'backend=%s\n' "$backend"
|
history -s "$input"
|
||||||
[ -n "$model" ] && printf 'model=%s\n' "$model"
|
case "$input" in
|
||||||
[ -n "$output" ] && printf 'output=%s\n' "$output"
|
/kill) printf 'kill %s\n' "$id" > "$MOUNT/ctl"; break ;;
|
||||||
printf 'parallel=%s\n' "$parallel"
|
"/q "*) printf '%s\n' "${input#/q }" > "$S/enqueue"
|
||||||
printf -- '---\n'
|
printf 'queued\n' >&2; continue ;;
|
||||||
printf '%s\n' "$prompt"
|
/*) printf '%s\n' "$input" > "$S/ctl" ;;
|
||||||
} > "$MOUNT/b/new" || die "failed to submit job"
|
*) printf '%s' "$input" > "$S/prompt" || { printf 'submit failed\n' >&2; continue; } ;;
|
||||||
|
|
||||||
rc=0
|
|
||||||
for i in $(seq 0 $((parallel - 1))); do
|
|
||||||
id="${name}-${i}"
|
|
||||||
B="$MOUNT/b/$id"
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
status=$(tr -d '[:space:]' < "$B/status" 2>/dev/null) || { sleep 0.05; continue; }
|
|
||||||
case "$status" in
|
|
||||||
done*) break ;;
|
|
||||||
failed*) rc=1; break ;;
|
|
||||||
*) sleep 0.05 ;;
|
|
||||||
esac
|
esac
|
||||||
|
sleep 0.15
|
||||||
|
while true; do
|
||||||
|
drain
|
||||||
|
is_idle && { drain; printf '\n'; break; }
|
||||||
|
sleep 0.05
|
||||||
done
|
done
|
||||||
|
|
||||||
[ "$parallel" -gt 1 ] && printf '=== %s ===\n' "$id"
|
|
||||||
cat "$B/result" 2>/dev/null
|
|
||||||
|
|
||||||
[ "$keep" -eq 0 ] && rm -r "$B" 2>/dev/null || true
|
|
||||||
done
|
done
|
||||||
|
|
||||||
exit $rc
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue