remove s/, u/, x/ script namespaces and 9P backing
All session scripts (s/sh, s/b, s/bfg, s/bbg, s/ls, s/kill, s/cleanup), utility scripts (u/optimize, u/complete, u/cascade, u/escalate), and internal scripts (x/bd, x/prime, x/freeloader, x/task) are removed. These are replaced by: - generate, complete, route files (ollie-9p rdwr) - integrated elevation broker - D-Bus/9P session management Also removes: - 9P rootFileOrder entries and permission map for script files - Script-serving catch-all in rootOpen - prependOlliePath (no x/ scripts to shadow PATH with) ollie-watchdog moved to contrib/scripts/ alongside ollie-remount.
This commit is contained in:
parent
ffe45c4f1f
commit
ddddb1f53b
|
|
@ -1,13 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# s/cleanup: kill all idle sessions.
|
||||
set -euo pipefail
|
||||
|
||||
OLLIE=${OLLIE:-$HOME/mnt/ollie}
|
||||
|
||||
remount_once() { ollie-remount 2>/dev/null; }
|
||||
|
||||
for sess in "$OLLIE"/s/*/; do
|
||||
[ -d "$sess" ] || { remount_once; [ -d "$sess" ] || continue; }
|
||||
state=$(awk -F= '$1=="state"{print $2; exit}' "$sess/cfg" 2>/dev/null | tr -d '[:space:]') || continue
|
||||
[ "$state" = "idle" ] && rm -r "$sess"
|
||||
done
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
OLLIE=${OLLIE:-$HOME/mnt/ollie}
|
||||
rm -r "${OLLIE}/s/$1" 2>/dev/null || { ollie-remount && rm -r "${OLLIE}/s/$1"; }
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
OLLIE=${OLLIE:-$HOME/mnt/ollie}
|
||||
cat "$OLLIE/s/idx" 2>/dev/null || { ollie-remount && cat "$OLLIE/s/idx"; }
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# u/cascade — script-driven hub-and-spoke cascading orchestrator.
|
||||
#
|
||||
# An expensive model decomposes a task into mechanical subtasks, then cheap
|
||||
# models execute them in parallel. The script (not an agent) coordinates.
|
||||
#
|
||||
# Usage: cascade [flags] [prompt...]
|
||||
# echo "prompt" | cascade [flags]
|
||||
#
|
||||
# Flags:
|
||||
# -pb BACKEND planner backend (default: $OLLIE_CASCADE_PLAN_BACKEND or anthropic)
|
||||
# -pm MODEL planner model (default: $OLLIE_CASCADE_PLAN_MODEL or claude-sonnet-4-20250514)
|
||||
# -wb BACKEND worker backend (default: $OLLIE_CASCADE_BACKEND or ollama)
|
||||
# -wm MODEL worker model (default: $OLLIE_CASCADE_MODEL or qwen2.5-coder:14b)
|
||||
# -max-workers N max concurrent workers (default: 8)
|
||||
# -retries N max attempts per worker (default: 1, no retry)
|
||||
# -synthesize collect worker results and ask the planner to produce a summary
|
||||
# -json-output structured JSON synthesis (implies -synthesize)
|
||||
set -euo pipefail
|
||||
|
||||
OLLIE="${OLLIE:-$HOME/mnt/ollie}"
|
||||
B="$OLLIE/s/b"
|
||||
|
||||
PB="${OLLIE_CASCADE_PLAN_BACKEND:-openrouter}"
|
||||
PM="${OLLIE_CASCADE_PLAN_MODEL:-deepseek/deepseek-v4-pro}"
|
||||
WB="${OLLIE_CASCADE_BACKEND:-openrouter}"
|
||||
WM="${OLLIE_CASCADE_MODEL:-deepseek/deepseek-v4-flash}"
|
||||
|
||||
die() { printf 'cascade: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
synthesize=0
|
||||
json_output=0
|
||||
max_workers=8
|
||||
retries=1
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-pb) PB=$2; shift ;;
|
||||
-pm) PM=$2; shift ;;
|
||||
-wb) WB=$2; shift ;;
|
||||
-wm) WM=$2; shift ;;
|
||||
-max-workers) max_workers=$2; shift ;;
|
||||
-retries) retries=$2; shift ;;
|
||||
-synthesize) synthesize=1 ;;
|
||||
-json-output) json_output=1; synthesize=1 ;;
|
||||
--) shift; break ;;
|
||||
-*) die "unknown flag: $1" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
task="$*"
|
||||
elif ! [ -t 0 ]; then
|
||||
task=$(cat)
|
||||
else
|
||||
die "prompt required"
|
||||
fi
|
||||
[ -z "$task" ] && die "empty prompt"
|
||||
|
||||
case "$max_workers" in
|
||||
''|*[!0-9]*|0) die "-max-workers must be a positive integer" ;;
|
||||
esac
|
||||
case "$retries" in
|
||||
''|*[!0-9]*|0) die "-retries must be a positive integer" ;;
|
||||
esac
|
||||
|
||||
# Step 1: Ask the planner to decompose into subtasks (JSON array).
|
||||
plan=$("$B" -backend "$PB" -model "$PM" -json \
|
||||
"Decompose this task into independent, mechanical subtasks that a weak model can execute without judgment. Each subtask must be fully self-contained (include all needed context). Output a JSON array of objects with \"id\" (short string) and \"instruction\" (complete task description). Keep it minimal — only decompose what benefits from parallelism.
|
||||
|
||||
TASK:
|
||||
$task")
|
||||
|
||||
# Validate we got JSON with correct schema.
|
||||
printf '%s' "$plan" | jq empty 2>/dev/null || die "planner did not return valid JSON: $plan"
|
||||
printf '%s' "$plan" | jq -e 'type=="array" and length>0 and all(.[]; (.id|type=="string" and length>0) and (.instruction|type=="string" and length>0))' >/dev/null \
|
||||
|| die "plan schema invalid (need array of {id: string, instruction: string})"
|
||||
|
||||
# Step 2: Spawn workers in parallel, collect session paths.
|
||||
count=$(printf '%s' "$plan" | jq 'length')
|
||||
[ "$count" -eq 0 ] && die "planner returned empty plan"
|
||||
|
||||
pids=()
|
||||
workers=()
|
||||
base="cascade-$(date +%s%N)"
|
||||
tmpdir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
for i in $(seq 0 $((count - 1))); do
|
||||
id=$(printf '%s' "$plan" | jq -r ".[$i].id")
|
||||
instruction=$(printf '%s' "$plan" | jq -r ".[$i].instruction")
|
||||
sid="${base}-${id}"
|
||||
workers+=("$sid")
|
||||
|
||||
# Throttle: wait for a slot if at max concurrency.
|
||||
while [ "$(jobs -rp | wc -l)" -ge "$max_workers" ]; do sleep 0.5; done
|
||||
|
||||
(
|
||||
attempt=0
|
||||
while [ "$attempt" -lt "$retries" ]; do
|
||||
attempt=$((attempt + 1))
|
||||
name="${sid}$( [ "$attempt" -gt 1 ] && echo "-r${attempt}" || true)"
|
||||
"$B" -name "$name" -backend "$WB" -model "$WM" -keep \
|
||||
"You are a worker agent. Execute the following task exactly. Output only the result.
|
||||
|
||||
$instruction" > "${tmpdir}/${sid}.out" 2>&1 && touch "${tmpdir}/${sid}.ok" && break
|
||||
# Backoff before retry.
|
||||
sleep "$((attempt * 2))"
|
||||
done
|
||||
echo "$attempt" > "${tmpdir}/${sid}.attempts"
|
||||
echo "$name" > "${tmpdir}/${sid}.session"
|
||||
) &
|
||||
pids+=($!)
|
||||
done
|
||||
|
||||
# Step 3: Wait for all workers.
|
||||
for pid in "${pids[@]}"; do wait "$pid" || true; done
|
||||
|
||||
# Step 4: Gather results as structured JSON array.
|
||||
MAX_OUTPUT=${OLLIE_CASCADE_MAX_OUTPUT:-8000} # max chars per worker output
|
||||
failures=0
|
||||
results_json="["
|
||||
first=1
|
||||
for sid in "${workers[@]}"; do
|
||||
if [ -f "${tmpdir}/${sid}.ok" ]; then
|
||||
status="done"
|
||||
else
|
||||
status="failed"
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
out=$(cat "${tmpdir}/${sid}.out" 2>/dev/null || echo "(no output)")
|
||||
attempts=$(cat "${tmpdir}/${sid}.attempts" 2>/dev/null || echo 1)
|
||||
session_name=$(cat "${tmpdir}/${sid}.session" 2>/dev/null || echo "$sid")
|
||||
if [ "${#out}" -gt "$MAX_OUTPUT" ]; then
|
||||
out="${out:0:$MAX_OUTPUT}
|
||||
...(truncated, ${#out} chars total)"
|
||||
fi
|
||||
[ "$first" -eq 1 ] && first=0 || results_json="${results_json},"
|
||||
results_json="${results_json}$(jq -n --arg id "$sid" --arg status "$status" --arg output "$out" --argjson attempts "$attempts" --arg session "$session_name" \
|
||||
'{id: $id, status: $status, attempts: $attempts, session: $session, output: $output}')"
|
||||
done
|
||||
results_json="${results_json}]"
|
||||
|
||||
# Step 5: Synthesize or just print results.
|
||||
# Exit code contract:
|
||||
# No synthesis: exit 1 if any worker failed (caller must handle partial results).
|
||||
# Synthesis: exit 0 — the planner accounts for failures in its answer.
|
||||
if [ "$synthesize" -eq 0 ]; then
|
||||
printf '%s\n' "$results_json" | jq .
|
||||
[ "$failures" -gt 0 ] && exit 1
|
||||
else
|
||||
synth_flags=(-backend "$PB" -model "$PM")
|
||||
if [ "$json_output" -eq 1 ]; then
|
||||
synth_flags+=(-json)
|
||||
synth_prompt="Synthesize these worker results into a structured JSON response for the original task. Note: workers with status \"failed\" did not complete successfully — include them in errors.
|
||||
|
||||
Output schema: {\"summary\": \"<one-line summary>\", \"answer\": \"<full synthesized answer>\", \"worker_results\": [{\"id\": \"<worker-id>\", \"status\": \"done|failed\", \"attempts\": <int>, \"session\": \"<session-name>\", \"output\": \"<worker output>\"}], \"errors\": [\"<description of any failures>\"]}
|
||||
|
||||
ORIGINAL TASK:
|
||||
$task
|
||||
|
||||
WORKER RESULTS (JSON):
|
||||
$results_json"
|
||||
else
|
||||
synth_prompt="Synthesize these worker results into a final, coherent answer to the original task. Note: workers with status \"failed\" did not complete successfully — account for this in your synthesis.
|
||||
|
||||
ORIGINAL TASK:
|
||||
$task
|
||||
|
||||
WORKER RESULTS (JSON):
|
||||
$results_json"
|
||||
fi
|
||||
"$B" "${synth_flags[@]}" "$synth_prompt"
|
||||
fi
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# u/complete: AI code completion via /complete endpoint.
|
||||
# Reads prefix from stdin, prints completion to stdout.
|
||||
set -euo pipefail
|
||||
|
||||
PREFIX_MAX=12000
|
||||
SUFFIX_MAX=1000
|
||||
|
||||
cmd=${0##*/}
|
||||
die() { printf '%s: %s\n' "$cmd" "$*" >&2; exit 1; }
|
||||
|
||||
for _arg; do
|
||||
[ "$_arg" = "-help" ] && cat <<'HELP' && exit 0
|
||||
usage: complete [-model MODEL] [-backend BACKEND] [-file NAME] [-suffix TEXT]
|
||||
echo "prefix" | complete -file main.go -suffix "rest of code"
|
||||
|
||||
Reads prefix from stdin, prints raw completion to stdout.
|
||||
|
||||
Flags:
|
||||
-model MODEL model (default: $OLLIE_COMPLETE_MODEL)
|
||||
-backend BACKEND backend (default: $OLLIE_COMPLETE_BACKEND)
|
||||
-file NAME filename for language context
|
||||
-suffix TEXT code after the cursor
|
||||
-context TEXT additional context (LSP symbols, completions, hover)
|
||||
-cwd DIR working directory
|
||||
-help show this help
|
||||
HELP
|
||||
done
|
||||
|
||||
model=${OLLIE_COMPLETE_MODEL:-}
|
||||
backend=${OLLIE_COMPLETE_BACKEND:-}
|
||||
file=
|
||||
suffix=
|
||||
context=
|
||||
cwd=
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-model) model=$2; shift ;;
|
||||
-backend) backend=$2; shift ;;
|
||||
-file) file=$2; shift ;;
|
||||
-suffix) suffix=$2; shift ;;
|
||||
-context) context=$2; shift ;;
|
||||
-cwd) cwd=$2; shift ;;
|
||||
-help) ;;
|
||||
-*) die "unknown flag: $1" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
[ -z "$model" ] && die "model required: set OLLIE_COMPLETE_MODEL or pass -model"
|
||||
[ -z "$backend" ] && die "backend required: set OLLIE_COMPLETE_BACKEND or pass -backend"
|
||||
|
||||
prefix=$(cat)
|
||||
|
||||
# Truncate to context budget
|
||||
[ ${#prefix} -gt $PREFIX_MAX ] && prefix="${prefix: -$PREFIX_MAX}"
|
||||
[ ${#suffix} -gt $SUFFIX_MAX ] && suffix="${suffix:0:$SUFFIX_MAX}"
|
||||
|
||||
# JSON-escape a string.
|
||||
jsonesc() {
|
||||
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' '\1' | sed 's/\x01/\\n/g'
|
||||
}
|
||||
|
||||
# Build JSON request for /complete endpoint
|
||||
json='{"prefix":"'$(jsonesc "$prefix")'"'
|
||||
json="$json,\"suffix\":\"$(jsonesc "$suffix")\""
|
||||
[ -n "$file" ] && json="$json,\"file\":\"$(jsonesc "$file")\""
|
||||
[ -n "$context" ] && json="$json,\"context\":\"$(jsonesc "$context")\""
|
||||
json="$json,\"cwd\":\"$(jsonesc "${cwd:-$PWD}")\""
|
||||
json="$json}"
|
||||
|
||||
# Write to /complete and read response (net/dns pattern)
|
||||
result=$(printf '%s' "$json" | 9p rdwr ollie/complete) || die "complete failed (is olliesrv running?)"
|
||||
|
||||
# Strip markdown code fences if the model wrapped the output.
|
||||
result=$(printf '%s' "$result" | sed '/^```[a-zA-Z]*$/d; /^```$/d')
|
||||
|
||||
# Strip prefix echo: if the result starts with a suffix of the prefix, remove it.
|
||||
tail_max=200
|
||||
[ ${#prefix} -lt $tail_max ] && tail_max=${#prefix}
|
||||
i=$tail_max
|
||||
while [ "$i" -gt 0 ]; do
|
||||
tail="${prefix: -$i}"
|
||||
case "$result" in
|
||||
"$tail"*)
|
||||
result="${result#"$tail"}"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
i=$((i - 1))
|
||||
done
|
||||
|
||||
printf '%s' "$result"
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# u/escalate — escalate a task to a stronger model.
|
||||
#
|
||||
# When a weak model can't handle a task, escalate sends it to a strong model
|
||||
# and returns the result inline (blocking).
|
||||
#
|
||||
# Usage: escalate [flags] [prompt...]
|
||||
# echo "prompt" | escalate [flags]
|
||||
#
|
||||
# Flags:
|
||||
# -backend B expert backend (default: $OLLIE_ESCALATE_BACKEND or openrouter)
|
||||
# -model M expert model (default: $OLLIE_ESCALATE_MODEL or anthropic/claude-sonnet-4-20250514)
|
||||
# -keep keep the expert session after completion (don't auto-cleanup)
|
||||
set -euo pipefail
|
||||
|
||||
OLLIE="${OLLIE:-$HOME/mnt/ollie}"
|
||||
BIN="$OLLIE/s/b"
|
||||
|
||||
BACKEND="${OLLIE_ESCALATE_BACKEND:-openrouter}"
|
||||
MODEL="${OLLIE_ESCALATE_MODEL:-anthropic/claude-sonnet-4-20250514}"
|
||||
|
||||
die() { printf 'escalate: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
keep=0
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-backend) BACKEND=$2; shift ;;
|
||||
-model) MODEL=$2; shift ;;
|
||||
-keep) keep=1 ;;
|
||||
--) shift; break ;;
|
||||
-*) die "unknown flag: $1" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
prompt="$*"
|
||||
elif ! [ -t 0 ]; then
|
||||
prompt=$(cat)
|
||||
else
|
||||
die "prompt required"
|
||||
fi
|
||||
[ -z "$prompt" ] && die "empty prompt"
|
||||
|
||||
flags=(-backend "$BACKEND" -model "$MODEL")
|
||||
[ "$keep" -eq 1 ] && flags+=(-keep)
|
||||
|
||||
"$BIN" "${flags[@]}" "You are an expert model escalated to handle a hard task. Apply rigorous reasoning and produce a correct, complete answer.
|
||||
|
||||
$prompt"
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# u/optimize: generate N candidate optimized prompts and select the best.
|
||||
set -euo pipefail
|
||||
|
||||
for _arg; do
|
||||
[ "$_arg" = "-help" ] && cat <<'HELP' && exit 0
|
||||
usage: optimize [flags] [prompt...]
|
||||
echo "prompt" | optimize [flags]
|
||||
|
||||
Generates N optimized candidates for a prompt, then judges and returns the best.
|
||||
|
||||
Flags:
|
||||
-n N number of candidates to generate (default: 3)
|
||||
-cb BACKEND candidate generation backend
|
||||
-cm MODEL candidate generation model
|
||||
-jb BACKEND judge backend
|
||||
-jm MODEL judge model
|
||||
-help show this help
|
||||
HELP
|
||||
done
|
||||
|
||||
n=3; cb=; cm=; jb=; jm=
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-n) n=$2; shift ;;
|
||||
-cb) cb=$2; shift ;;
|
||||
-cm) cm=$2; shift ;;
|
||||
-jb) jb=$2; shift ;;
|
||||
-jm) jm=$2; shift ;;
|
||||
-help) ;;
|
||||
--) shift; break ;;
|
||||
-*) printf 'optimize: unknown flag: %s\n' "$1" >&2; exit 1 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
prompt="$*"
|
||||
elif ! [ -t 0 ]; then
|
||||
prompt=$(cat)
|
||||
else
|
||||
printf 'optimize: prompt required\n' >&2; exit 1
|
||||
fi
|
||||
|
||||
[ -z "$prompt" ] && { printf 'optimize: empty prompt\n' >&2; exit 1; }
|
||||
|
||||
B="${0%/*}/../s/b"
|
||||
|
||||
c_flags=()
|
||||
j_flags=()
|
||||
[ -n "$cb" ] && c_flags+=(-backend "$cb")
|
||||
[ -n "$cm" ] && c_flags+=(-model "$cm")
|
||||
[ -n "$jb" ] && j_flags+=(-backend "$jb")
|
||||
[ -n "$jm" ] && j_flags+=(-model "$jm")
|
||||
|
||||
printf 'generating %d candidates...\n' "$n" >&2
|
||||
candidates=$("$B" "${c_flags[@]}" -parallel "$n" \
|
||||
"Optimize the following prompt. Return only the optimized prompt, no explanation or preamble:
|
||||
|
||||
$prompt")
|
||||
|
||||
printf 'judging...\n' >&2
|
||||
"$B" "${j_flags[@]}" \
|
||||
"Review these candidate prompts and return only the single best one, no explanation or preamble:
|
||||
|
||||
$candidates"
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Wrapper for bd that resolves BEADS_DIR by walking up from CWD when unset.
|
||||
# Placed in $OLLIE/x/ so it shadows the real bd on PATH for tool subprocesses.
|
||||
if [ -z "$BEADS_DIR" ]; then
|
||||
dir="$PWD"
|
||||
while [ "$dir" != "/" ] && [ -e "$dir/.git" ]; do
|
||||
if [ -d "$dir/.beads" ]; then
|
||||
export BEADS_DIR="$dir/.beads"
|
||||
break
|
||||
fi
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
fi
|
||||
exec "$HOME/.local/bin/bd" "$@"
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# x/freeloader: turnError hook handler for free-model sessions on OpenRouter.
|
||||
#
|
||||
# Intercepts rate_limit and tool_unsupported errors on :free models, walks
|
||||
# through every viable free model once per round, and resubmits the previous
|
||||
# prompt on each switch. When the pool is exhausted, clears the tried list
|
||||
# and exits 1 so normal error handling takes over.
|
||||
#
|
||||
# Configure in an agent .json:
|
||||
# { "hooks": { "turnError": "$OLLIE/x/freeloader $OLLIE_SESSION_ID" } }
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 — error intercepted, switched model and resubmitted
|
||||
# 1 — pool exhausted or error not applicable; normal handling proceeds
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
OLLIE="${OLLIE:-$HOME/mnt/ollie}"
|
||||
CFG="${XDG_CONFIG_HOME:-$HOME/.config}/ollie"
|
||||
BLACKLIST="$CFG/freeloader-blacklist"
|
||||
cmd=${0##*/}
|
||||
|
||||
die() { printf '%s: %s\n' "$cmd" "$*" >&2; exit 1; }
|
||||
|
||||
[ $# -ne 1 ] && die "usage: freeloader <session-id>"
|
||||
|
||||
SID="$1"
|
||||
B="$OLLIE/s/$SID"
|
||||
|
||||
[ -d "$B" ] || die "session not found: $SID"
|
||||
|
||||
error_type="${OLLIE_ERROR_TYPE:-}"
|
||||
current_model="${OLLIE_MODEL:-$(grep '^model=' "$B/cfg" 2>/dev/null | cut -d= -f2-)}"
|
||||
|
||||
# Only handle rate_limit and tool_unsupported.
|
||||
case "$error_type" in
|
||||
rate_limit|tool_unsupported) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
|
||||
# Only act on :free models.
|
||||
case "$current_model" in
|
||||
*:free) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
|
||||
# For tool_unsupported: permanently blacklist the current model.
|
||||
if [ "$error_type" = "tool_unsupported" ]; then
|
||||
mkdir -p "$CFG"
|
||||
if ! grep -qxF "$current_model" "$BLACKLIST" 2>/dev/null; then
|
||||
printf '%s\n' "$current_model" >> "$BLACKLIST"
|
||||
printf '%s: blacklisted %s (tool_unsupported)\n' "$cmd" "$current_model" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Per-session tried list: tracks models attempted in the current round.
|
||||
TRIED="$CFG/freeloader-tried-$SID"
|
||||
mkdir -p "$CFG"
|
||||
|
||||
# Mark current model as tried.
|
||||
if ! grep -qxF "$current_model" "$TRIED" 2>/dev/null; then
|
||||
printf '%s\n' "$current_model" >> "$TRIED"
|
||||
fi
|
||||
|
||||
# Build the full sorted :free pool (blacklist excluded).
|
||||
mapfile -t pool < <(
|
||||
cat "$B/models" 2>/dev/null \
|
||||
| grep ':free' \
|
||||
| sort \
|
||||
| { [ -f "$BLACKLIST" ] && grep -vxFf "$BLACKLIST" || cat; }
|
||||
)
|
||||
|
||||
# Find first model not yet tried this round.
|
||||
next_model=""
|
||||
for m in "${pool[@]}"; do
|
||||
if ! grep -qxF "$m" "$TRIED" 2>/dev/null; then
|
||||
next_model="$m"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$next_model" ]; then
|
||||
printf '%s: all free models exhausted, giving up\n' "$cmd" >&2
|
||||
rm -f "$TRIED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Switch model and resubmit the previous prompt.
|
||||
printf 'model %s\n' "$next_model" > "$B/ctl" || die "failed to switch model"
|
||||
prev=$(cat "$B/prompt.prev" 2>/dev/null) || die "prompt.prev not available"
|
||||
[ -z "$prev" ] && die "prompt.prev is empty"
|
||||
printf '%s\n' "$prev" > "$B/fifo.in" || die "failed to resubmit prompt"
|
||||
|
||||
printf '%s: %s → %s\n' "$cmd" "$current_model" "$next_model" >&2
|
||||
exit 0
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Print a prompt file from $OLLIE_PROMPTS_PATH to stdout.
|
||||
# Usage: prime <name> (resolves <name> or <name>.md under OLLIE_PROMPTS_PATH)
|
||||
# Resolution and variable expansion is now handled by the Go prompt resolver;
|
||||
# this script is a convenience wrapper for manual/CLI use.
|
||||
set -euo pipefail
|
||||
|
||||
PROMPTS_PATH="${OLLIE_PROMPTS_PATH:-${HOME}/.config/ollie/prompts}"
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "usage: prime <name>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NAME="$1"
|
||||
|
||||
IFS=: read -ra DIRS <<< "$PROMPTS_PATH"
|
||||
for dir in "${DIRS[@]}"; do
|
||||
[ -z "$dir" ] && continue
|
||||
for path in "$dir/$NAME" "$dir/$NAME.md"; do
|
||||
if [ -f "$path" ]; then
|
||||
cat "$path"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "prime: prompt not found: $NAME" >&2
|
||||
exit 1
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Task dispatcher.
|
||||
# list: always shows s/{sid}/plan; additionally bd list --status open if .beads present.
|
||||
|
||||
OLLIE="${OLLIE:-$HOME/mnt/ollie}"
|
||||
|
||||
show_plan() {
|
||||
[ -z "$OLLIE_SESSION_ID" ] && return
|
||||
plan="$OLLIE/s/$OLLIE_SESSION_ID/plan"
|
||||
[ -s "$plan" ] && echo "## Session Plan" && echo && cat "$plan" && echo
|
||||
}
|
||||
|
||||
dir="$PWD"
|
||||
while [ "$dir" != "/" ]; do
|
||||
if [ -d "$dir/.beads" ]; then
|
||||
show_plan; exec bd list --status open
|
||||
fi
|
||||
[ ! -e "$dir/.git" ] && break
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
|
||||
show_plan
|
||||
exit 0
|
||||
|
|
@ -59,13 +59,6 @@ var Perms = map[string]Perm{
|
|||
Files: map[string]os.FileMode{
|
||||
"new": 0666,
|
||||
"idx": 0444,
|
||||
"ls": 0555,
|
||||
"kill": 0555,
|
||||
"sh": 0550,
|
||||
"b": 0555,
|
||||
"bfg": 0555,
|
||||
"bbg": 0555,
|
||||
"cleanup": 0555,
|
||||
},
|
||||
},
|
||||
PathSessionDir: {DirMode: 0755},
|
||||
|
|
|
|||
|
|
@ -12,13 +12,12 @@ import (
|
|||
|
||||
"ollie/agent"
|
||||
olog "ollie/log"
|
||||
"ollie/paths"
|
||||
coresession "ollie/session"
|
||||
"ollie/skills"
|
||||
"ollie/toolsrv"
|
||||
)
|
||||
|
||||
var rootFileOrder = []string{"new", "idx", "ls", "kill", "sh", "b", "bfg", "bbg", "cleanup"}
|
||||
var rootFileOrder = []string{"new", "idx"}
|
||||
|
||||
// FileMode returns the mode for a fixed session file,
|
||||
// or 0 and false if the name is not a fixed file.
|
||||
|
|
@ -341,18 +340,6 @@ func rootOpen(rs *rootState, name string) (File, error) {
|
|||
BlockingReadFn: notBlocking,
|
||||
}, nil
|
||||
}
|
||||
if _, ok := Perms[PathSessions].Files[name]; ok {
|
||||
return &FileConfig{
|
||||
StatFn: func() (os.FileInfo, error) {
|
||||
return &SyntheticFileInfo{Name_: name, Mode_: Perms[PathSessions].Files[name]}, nil
|
||||
},
|
||||
ReadFn: func() ([]byte, error) {
|
||||
return rs.cfg.ReadFile(paths.CfgDir() + "/scripts/session/" + name)
|
||||
},
|
||||
WriteFn: func([]byte) error { return fmt.Errorf("%s: not writable", name) },
|
||||
BlockingReadFn: notBlocking,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Hierarchical paths: {id}/{file} or {id}/agent/{aid}/{file}
|
||||
parts = strings.SplitN(name, "/", 4)
|
||||
|
|
|
|||
16
justfile
16
justfile
|
|
@ -168,20 +168,6 @@ install-data:
|
|||
|
||||
install-scripts:
|
||||
@echo === Installing scripts ===
|
||||
mkdir -p {{cfg}}/scripts/s {{cfg}}/scripts/u {{cfg}}/scripts/x
|
||||
install -m755 contrib/scripts/s/sh {{cfg}}/scripts/s/sh
|
||||
install -m755 contrib/scripts/s/ls {{cfg}}/scripts/s/ls
|
||||
install -m755 contrib/scripts/s/kill {{cfg}}/scripts/s/kill
|
||||
install -m755 contrib/scripts/s/b {{cfg}}/scripts/s/b
|
||||
install -m755 contrib/scripts/s/bfg {{cfg}}/scripts/s/bfg
|
||||
install -m755 contrib/scripts/s/bbg {{cfg}}/scripts/s/bbg
|
||||
install -m755 contrib/scripts/s/cleanup {{cfg}}/scripts/s/cleanup
|
||||
install -m755 contrib/scripts/u/optimize {{cfg}}/scripts/u/optimize
|
||||
install -m755 contrib/scripts/u/complete {{cfg}}/scripts/u/complete
|
||||
install -m755 contrib/scripts/u/cascade {{cfg}}/scripts/u/cascade
|
||||
install -m755 contrib/scripts/x/bd {{cfg}}/scripts/x/bd
|
||||
install -m755 contrib/scripts/x/prime {{cfg}}/scripts/x/prime
|
||||
install -m755 contrib/scripts/x/freeloader {{cfg}}/scripts/x/freeloader
|
||||
|
||||
install-autostart:
|
||||
@echo === Installing autostart files ===
|
||||
|
|
@ -197,7 +183,7 @@ install-contrib:
|
|||
@echo === Installing contrib scripts ===
|
||||
mkdir -p {{bin}}
|
||||
install -m755 contrib/scripts/ollie-remount {{bin}}/ollie-remount
|
||||
install -m755 contrib/scripts/s/ollie-watchdog {{bin}}/ollie-watchdog
|
||||
install -m755 contrib/scripts/ollie-watchdog {{bin}}/ollie-watchdog
|
||||
|
||||
# === Uninstall ===
|
||||
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ func (e *Server) executeWithStdin(ctx context.Context, code, language string, ti
|
|||
filtered = append(filtered, ev)
|
||||
}
|
||||
}
|
||||
cmd.Env = prependOlliePath(filtered, paths.CfgDir())
|
||||
cmd.Env = filtered
|
||||
cmd.Env = append(cmd.Env, "OLLIE_TOOLS_PATH="+ToolsPath())
|
||||
for k, v := range e.envExtra {
|
||||
cmd.Env = append(cmd.Env, k+"="+v)
|
||||
|
|
@ -644,23 +644,6 @@ func (e *Server) executeWithStdin(ctx context.Context, code, language string, ti
|
|||
}
|
||||
}
|
||||
|
||||
// prependOlliePath returns env with $OLLIE_CFG_PATH/scripts/x/ prepended to PATH so wrapper
|
||||
// scripts placed there shadow system binaries.
|
||||
func prependOlliePath(env []string, cfgDir string) []string {
|
||||
if cfgDir == "" {
|
||||
return env
|
||||
}
|
||||
xdir := filepath.Join(cfgDir, "scripts", "x")
|
||||
result := make([]string, 0, len(env))
|
||||
for _, e := range env {
|
||||
if strings.HasPrefix(e, "PATH=") {
|
||||
e = "PATH=" + xdir + string(filepath.ListSeparator) + e[5:]
|
||||
}
|
||||
result = append(result, e)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// plan9Namespace computes the plan9port namespace directory from the environment.
|
||||
// Convention: $NAMESPACE if set, else /tmp/ns.<user>.<display> where display is
|
||||
// $DISPLAY with trailing .0 stripped and / replaced by _.
|
||||
|
|
|
|||
Loading…
Reference in New Issue