From d8e0b9b5ba0ceb670346693a50dbfbf3e4bcaffc Mon Sep 17 00:00:00 2001
From: Levi Neely <141506390+lneely@users.noreply.github.com>
Date: Sat, 18 Jul 2026 16:00:54 +0200
Subject: [PATCH] 9p: add /complete file for stateless code completion
Follows the Plan 9 /net/dns pattern: per-fid request-response.
Write JSON request (or plain prefix), write blocks during LLM call,
read returns the completion result. Per-fid state means concurrent
clients get independent request/response pairs.
Also includes the Complete method, findOrCreateCopilot, and noise
stripping helpers in the session package.
---
main.go | 10 ++-
server/server.go | 45 +++++++++++--
session/session.go | 162 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 209 insertions(+), 8 deletions(-)
diff --git a/main.go b/main.go
index 6e5e00d..fce81bf 100644
--- a/main.go
+++ b/main.go
@@ -354,7 +354,7 @@ func NewRootStore() *fs.Tree {
if _, ok := readEntries[name]; ok {
return name, nil
}
- if name == "ctl" {
+ if name == "ctl" || name == "complete" {
return name, nil
}
return "", fmt.Errorf("%s: not found", name)
@@ -368,6 +368,14 @@ func NewRootStore() *fs.Tree {
}, nil
}),
fs.WithOpener(func(_ []string, name string) (fs.File, error) {
+ if name == "complete" {
+ return &fs.FileConfig{
+ StatFn: func() (os.FileInfo, error) { return &fs.SyntheticFileInfo{Name_: "complete", Mode_: 0666}, nil },
+ ReadFn: func() ([]byte, error) { return nil, nil },
+ WriteFn: func([]byte) error { return nil },
+ BlockingReadFn: notBlocking,
+ }, nil
+ }
if name == "ctl" {
return &fs.FileConfig{
StatFn: func() (os.FileInfo, error) { return &fs.SyntheticFileInfo{Name_: "ctl", Mode_: 0666}, nil },
diff --git a/server/server.go b/server/server.go
index c5a6ca6..e5e4deb 100644
--- a/server/server.go
+++ b/server/server.go
@@ -4,6 +4,7 @@ package server
import (
"context"
+ "encoding/json"
"fmt"
"hash/fnv"
"io"
@@ -38,12 +39,13 @@ const (
// fid tracks per-descriptor state for a single 9P connection.
type fid struct {
- path string
- qid plan9.Qid
- mode uint8
- writeBuf []byte
- waitBase string // for *wait files: value snapshotted at open time
- dirCache []byte // cached serialized dir entries for readdir
+ path string
+ qid plan9.Qid
+ mode uint8
+ writeBuf []byte
+ waitBase string // for *wait files: value snapshotted at open time
+ dirCache []byte // cached serialized dir entries for readdir
+ completeResult []byte // for /complete: result of last write (per-fid state)
}
// connState tracks all open fids for a single 9P connection.
@@ -753,6 +755,12 @@ func (s *Server) read(cs *connState, fc *plan9.Fcall, ctx context.Context) *plan
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(len(data)), Data: data}
}
+ // /complete: return per-fid result from previous write
+ if path == "/complete" {
+ s.log.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
+ return s.readSlice(fc, f.completeResult)
+ }
+
s.log.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
entry, err := s.openEntry(path)
if err != nil {
@@ -840,6 +848,29 @@ func (s *Server) write(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
return errFcall(fc, "bad fid")
}
s.log.Debug("Twrite fid=%d path=%q offset=%d len=%d", fc.Fid, f.path, fc.Offset, len(fc.Data))
+
+ // /complete: synchronous request-response (per-fid state, like /net/dns)
+ if f.path == "/complete" {
+ cs.mu.Unlock()
+ var req struct {
+ CWD string `json:"cwd"`
+ FilePath string `json:"file"`
+ Prefix string `json:"prefix"`
+ Suffix string `json:"suffix"`
+ ExtraContext string `json:"context"`
+ }
+ if err := json.Unmarshal(fc.Data, &req); err != nil {
+ // If not JSON, treat entire write as prefix (simple mode)
+ req.Prefix = strings.TrimSpace(string(fc.Data))
+ }
+ result, err := s.sessionMgr.Complete(req.CWD, req.FilePath, req.Prefix, req.Suffix, req.ExtraContext)
+ if err != nil {
+ return errFcall(fc, err.Error())
+ }
+ f.completeResult = []byte(result)
+ return &plan9.Fcall{Type: plan9.Rwrite, Tag: fc.Tag, Count: uint32(len(fc.Data))}
+ }
+
// Accumulate; the 9P client may split large writes across multiple Twrite messages.
end := int(fc.Offset) + len(fc.Data)
if end > len(f.writeBuf) {
@@ -1013,7 +1044,7 @@ func (s *Server) buildDirData(path string) []byte {
var dirs []plan9.Dir
if path == "/" {
- rootEntries := []string{"agents", "backends", "ctl", "help", "models", "s"}
+ rootEntries := []string{"agents", "backends", "complete", "ctl", "help", "models", "s"}
for _, name := range rootEntries {
fpath := "/" + name
st := s.makeStat(fpath)
diff --git a/session/session.go b/session/session.go
index f16fa02..4451c6a 100644
--- a/session/session.go
+++ b/session/session.go
@@ -3,6 +3,7 @@ package session
import (
"context"
"fmt"
+ "hash/crc32"
"os"
"path/filepath"
"sort"
@@ -1081,3 +1082,164 @@ func FormatEvent(ev agent.Event) []byte {
func squashWhitespace(s string) string {
return strings.Join(strings.Fields(s), " ")
}
+
+// --- Code Completion ---
+
+// Complete performs a single-shot code completion using a dedicated copilot session.
+func (s *Manager) Complete(cwd, filePath, prefix, suffix, extraContext string) (string, error) {
+ if cwd == "" {
+ cwd, _ = os.Getwd()
+ }
+ cwd = paths.ExpandHome(os.ExpandEnv(cwd))
+
+ model := os.Getenv("OLLIE_COMPLETE_MODEL")
+ backendName := os.Getenv("OLLIE_COMPLETE_BACKEND")
+ if model == "" || backendName == "" {
+ return "", fmt.Errorf("OLLIE_COMPLETE_MODEL and OLLIE_COMPLETE_BACKEND must be set")
+ }
+
+ const prefixMax = 12000
+ const suffixMax = 1000
+ if len(prefix) > prefixMax {
+ prefix = prefix[len(prefix)-prefixMax:]
+ }
+ if len(suffix) > suffixMax {
+ suffix = suffix[:suffixMax]
+ }
+
+ sessID := s.findOrCreateCopilot(cwd, backendName, model)
+ if sessID == "" {
+ return "", fmt.Errorf("failed to create copilot session")
+ }
+
+ s.mu.RLock()
+ sess, ok := s.sessions[sessID]
+ s.mu.RUnlock()
+ if !ok {
+ return "", fmt.Errorf("copilot session disappeared")
+ }
+
+ fileHint := ""
+ if filePath != "" {
+ fileHint = " in " + filePath
+ }
+ contextBlock := ""
+ if extraContext != "" {
+ contextBlock = "\n" + extraContext
+ }
+ prompt := fmt.Sprintf(`Implement the code at the cursor%s. The prefix ends at the point where new code is needed. Write the implementation — do not echo stubs, TODOs, or placeholder returns from the prefix. Output ONLY raw code. No reasoning, no shell commands, no explanations, no markdown fences, no backticks, no preamble. Your entire response must be valid code that can be inserted directly into the file.
+%s
+
+%s
+
+
+%s
+`, fileHint, contextBlock, prefix, suffix)
+
+ sess.Core.Submit(sess.Ctx, "/clear")
+ sess.Core.Submit(sess.Ctx, prompt)
+
+ for {
+ state := sess.Core.State()
+ if state == "idle" {
+ break
+ }
+ next, ok := sess.Core.WaitChange(sess.Ctx, agent.WatchState, state)
+ if !ok {
+ return "", fmt.Errorf("copilot session cancelled")
+ }
+ if next == "idle" {
+ break
+ }
+ }
+
+ result := sess.Core.Reply()
+ result = stripCompletionNoise(result)
+ result = stripPrefixEcho(prefix, result)
+ return result, nil
+}
+
+func (s *Manager) findOrCreateCopilot(cwd, backendName, modelName string) string {
+ sessID := fmt.Sprintf("%d-copilot", crc32Str(cwd))
+
+ s.mu.RLock()
+ _, exists := s.sessions[sessID]
+ s.mu.RUnlock()
+ if exists {
+ return sessID
+ }
+
+ cfg := LoadAgentConfig(s.cfg.AgentsDir, "copilot", nil)
+ be, err := backend.NewWithName(backendName)
+ if err != nil {
+ return ""
+ }
+ if modelName != "" {
+ be.SetModel(modelName)
+ }
+
+ uname := s.nextUname()
+ newDisp := tools.NewDispatcherFunc(map[string]func() tools.Server{
+ "execute": execute.Decl(cwd),
+ })
+ rt := agent.BuildRuntime(cfg, newDisp(), cwd, []string{"OLLIE_SESSION_ID=" + sessID})
+
+ core := agent.NewAgentCore(agent.AgentCoreConfig{
+ Backend: be,
+ AgentName: "copilot",
+ AgentsDir: s.cfg.AgentsDir,
+ SessionsDir: s.cfg.SessionsDir,
+ SessionID: sessID,
+ Uname: uname,
+ CWD: cwd,
+ Runtime: rt,
+ NewDispatcher: newDisp,
+ Log: s.cfg.Sink.NewLogger("copilot"),
+ })
+
+ ctx, cancel := context.WithCancel(context.Background())
+ sess := NewSession(sessID, core, ctx, cancel)
+ sess.uname = uname
+
+ s.mu.Lock()
+ s.sessions[sessID] = sess
+ s.mu.Unlock()
+ return sessID
+}
+
+func stripCompletionNoise(s string) string {
+ var lines []string
+ for _, line := range strings.Split(s, "\n") {
+ trimmed := strings.TrimSpace(line)
+ if strings.HasPrefix(trimmed, "```") {
+ continue
+ }
+ if trimmed == "" || trimmed == "" ||
+ trimmed == "" || trimmed == "" {
+ continue
+ }
+ if strings.HasPrefix(trimmed, ":: ") {
+ continue
+ }
+ lines = append(lines, line)
+ }
+ return strings.Join(lines, "\n")
+}
+
+func stripPrefixEcho(prefix, result string) string {
+ tailMax := 200
+ if len(prefix) < tailMax {
+ tailMax = len(prefix)
+ }
+ for i := tailMax; i > 0; i-- {
+ tail := prefix[len(prefix)-i:]
+ if strings.HasPrefix(result, tail) {
+ return result[len(tail):]
+ }
+ }
+ return result
+}
+
+func crc32Str(s string) uint32 {
+ return crc32.ChecksumIEEE([]byte(s))
+}