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}')