diff --git a/agents/copilot.json b/agents/copilot.json index 87acdfc..32fa871 100644 --- a/agents/copilot.json +++ b/agents/copilot.json @@ -1,4 +1,9 @@ { "prompt": [], - "trustedTools": [] + "trustedTools": [], + "hooks": { + "turnError": [ + "$OLLIE/x/freeloader $OLLIE_SESSION_ID" + ] + } } diff --git a/scripts/u/complete b/scripts/u/complete index bb695c8..364653f 100644 --- a/scripts/u/complete +++ b/scripts/u/complete @@ -6,7 +6,6 @@ PREFIX_MAX=4000 SUFFIX_MAX=1000 MOUNT=${OLLIE:-$HOME/mnt/ollie} -BFG="${0%/*}/../s/bfg" cmd=${0##*/} die() { printf '%s: %s\n' "$cmd" "$*" >&2; exit 1; } @@ -42,6 +41,41 @@ done [ -z "${winid:-}" ] || [ "$winid" = "0" ] && die "must be run from an acme window" +# Find or create a copilot session for the current working directory. +# Reuses an existing *-copilot session in this cwd if one is alive, +# otherwise spawns a new one. +find_or_create_session() { + local target_cwd="$1" + local sdir state scwd id kv deadline + + while IFS= read -r line; do + id=${line%%$'\t'*} + case "$id" in *-copilot) ;; *) continue ;; esac + sdir="$MOUNT/s/$id" + [ -d "$sdir" ] || continue + scwd=$(cat "$sdir/cwd" 2>/dev/null) || continue + [ "$scwd" = "$target_cwd" ] || continue + state=$(cat "$sdir/state" 2>/dev/null) || continue + case "$state" in failed*|error*) continue ;; esac + printf '%s\n' "$id" + return 0 + done < "$MOUNT/s/idx" + + id="$(date +%s%N)-copilot" + kv="name=${id} +cwd=${target_cwd} +agent=copilot +backend=${backend} +model=${model}" + printf '%s\n' "$kv" > "$MOUNT/s/new" || die "failed to create copilot session" + + deadline=$(( $(date +%s) + 5 )) + until [ -d "$MOUNT/s/$id" ] || [ "$(date +%s)" -ge "$deadline" ]; do sleep 0.05; done + [ -d "$MOUNT/s/$id" ] || die "timeout waiting for copilot session" + + printf '%s\n' "$id" +} + # Get filename for language context (last field of ctl line 1) filename=$(9p read acme/$winid/ctl | awk 'NR==1{print $NF}') @@ -62,16 +96,29 @@ suffix=$(9p read acme/$winid/data) prefix="${prefix: -$PREFIX_MAX}" suffix="${suffix:0:$SUFFIX_MAX}" -# Query model -result=$("$BFG" -agent copilot -model "$model" -backend "$backend" \ - "Complete the code at the cursor in ${filename}. Output ONLY the text to insert — no explanation, no markdown, no preamble. +# Find or create the copilot session, then submit +sid=$(find_or_create_session "$PWD") +B="$MOUNT/s/$sid" + +printf '%s\n' "Complete the code at the cursor in ${filename}. Output ONLY the text to insert — no explanation, no markdown, no preamble. ${prefix} ${suffix} -") +" > "$B/prompt" + +# Wait for idle +while true; do + state=$(cat "$B/statewait" 2>/dev/null | tr -d '[:space:]') || break + [ "$state" = "idle" ] && break +done + +# Read result from offset, then clear context for next completion +offset=$(cat "$B/offset" 2>/dev/null || echo 0) +result=$(tail -c +$((offset + 1)) "$B/chat" 2>/dev/null) +echo "clear" > "$B/ctl" # Write completion to a new acme window newid=$(9p read acme/new/ctl | awk 'NR==1{print $1}')