From 45d1b6b77e790980d8a194ceeebd8a2ab55a299d Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 3 May 2026 22:03:01 +0200 Subject: [PATCH] readme: add "What you get" section; update submodules - README.md: add feature summary with bulleted list - acme: add README documenting ollie-acme and Kmpl - el: refactor completion to shell out to u/complete - u/complete: improve prompt and strip leaked tags --- README.md | 18 ++++++++++++++++++ acme | 2 +- el | 2 +- scripts/u/complete | 22 +++++++++++++++++++--- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 371632b..18e1146 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,24 @@ Ollie starts from a simple, slightly silly question: *What might an AI agent look like in [Plan 9](https://www.usenix.org/legacy/publications/compsystems/1995/sum_pike.pdf)?* From there follow two more: *What happens if agent primitives are exposed as an ordinary filesystem?* and *How much can we subtract from agent implementations while still being useful?* The result is not a conventional "agent framework" but a small Go runtime and 9P‑backed filesystem surface that defines what an agent is, then exposes its state and behaviors as regular files and I/O streams, so that the surrounding environment (shell scripts, TUIs, web apps, cron, containers, and other OS facilities) can handle orchestration, scheduling, workflows, and interfaces instead. The same primitives scale from simple copilot use cases — `u/complete` manages a session per working directory for ghost‑text code completion in [acme](http://acme.cat-v.org) — through interactive shells and one‑shot pipelines, up to multi‑agent workflows coordinated by scripts, other agents, or both. +## What you get + +- **Interactive AI shell** — `s/sh` gives you a readline prompt that resumes your last session per directory, with streaming output and live model/backend switching +- **One-shot queries that compose with Unix pipes** — `cat error.log | s/bfg "what caused this?" | s/bfg "suggest a fix"` +- **Parallel fan-out** — `s/bfg -parallel 4` spawns N agents on the same prompt and collects results +- **Multi-agent workflows in plain shell** — create named sessions, pass prompts between them via files, coordinate with `statewait`; no framework or SDK +- **Subagent delegation** — agents can fork ephemeral subagents that run independently and return results +- **Any model, any backend** — Ollama (local), OpenAI, Anthropic, OpenRouter, GitHub Copilot, Kiro; switch per-session with one write +- **Sandboxed execution** — every tool call runs inside a Landlock sandbox with configurable filesystem access +- **Extensible via plain scripts** — drop executables into a directory and the agent picks them up; built-in tools cover file I/O, LSP (go-to-definition, references, rename, diagnostics), persistent memory, web search, browser screenshots, and task tracking +- **Domain skills** — teach the agent your project's conventions with a markdown file; loaded on demand +- **AI code completion** — `u/complete` reads a prefix from stdin and prints the completion to stdout; plug it into any editor that can shell out +- **Multiple frontends** — terminal (`s/sh`), acme (`ollie-acme` + `Kmpl`), Emacs (`ellie`), and a browser-based web UI; all talk to the same 9P server +- **Remote access** — mount a remote server's namespace locally with `9pfuse`, or use the HTTP gateway with `curl` or the web UI +- **Store federation** — point tools or transcripts at a remote 9P mount to share across machines +- **Prompt optimization** — `u/optimize` generates N candidate prompts in parallel, then judges them to return the best one +- **Automatic context compaction** — long conversations are summarized transparently when approaching the model's context limit + ## Getting Started Clone with submodules: diff --git a/acme b/acme index 23df25a..f4e844b 160000 --- a/acme +++ b/acme @@ -1 +1 @@ -Subproject commit 23df25acdf04d1cd06725164b9df84ed91993ffa +Subproject commit f4e844b0a645542127ccf16eeeaef8e8d4f1f74f diff --git a/el b/el index b220308..de3d08c 160000 --- a/el +++ b/el @@ -1 +1 @@ -Subproject commit b22030827a77995a4fc82372483f249db407609f +Subproject commit de3d08ce145218db8522c77c81d30248781ade90 diff --git a/scripts/u/complete b/scripts/u/complete index c7fc2dd..7162782 100755 --- a/scripts/u/complete +++ b/scripts/u/complete @@ -96,7 +96,7 @@ B="$MOUNT/s/$sid" file_hint= [ -n "$file" ] && file_hint=" in ${file}" -printf '%s\n' "Complete the code at the cursor${file_hint}. Continue from the prefix to finish the current function, block, or logical unit. Output ONLY the raw text to insert at the cursor position. Do NOT wrap the output in markdown code fences or backticks. No explanation, no preamble. +printf '%s\n' "Complete the code at the cursor${file_hint}. The prefix is already written. Output ONLY the new text that comes after the prefix — do NOT repeat any part of the prefix. Continue to finish the current function, block, or logical unit. No markdown code fences, no backticks, no explanation, no preamble. ${prefix} @@ -114,11 +114,27 @@ 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) -# Strip markdown code fences if the model wrapped the output. -result=$(printf '%s' "$result" | sed '/^```[a-zA-Z]*$/d; /^```$/d') +# Strip markdown code fences and leaked XML tags if the model wrapped the output. +result=$(printf '%s' "$result" | sed '/^```[a-zA-Z]*$/d; /^```$/d; /^<\/\?\(prefix\|suffix\)>$/d') # Print info lines (:: prefix) to stderr; keep only code. printf '%s\n' "$result" | grep '^:: ' >&2 || true result=$(printf '%s' "$result" | grep -v '^:: ') echo "clear" > "$B/ctl" +# Strip prefix echo: if the result starts with a suffix of the prefix, remove it. +# Check progressively shorter tails of the prefix (up to 200 chars). +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"