From 7e29d28848747b847eb019e1b26e9b110e12aee9 Mon Sep 17 00:00:00 2001 From: Ollie Agent Date: Fri, 7 Aug 2026 07:36:58 +0200 Subject: [PATCH] =?UTF-8?q?remove=20agent/complete.go=20=E2=80=94=20comple?= =?UTF-8?q?tions=20now=20go=20through=20/generate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Delete agent/complete.go (110 lines) and its requestComplete handler - Remove /complete 9P file from fs/spec.go - Update KDE kate plugin to build the completion prompt inline and call ollie-9p rdwr generate instead of ollie-9p rdwr complete - StripCompletionNoise and stripPrefixEcho moved into C++ helpers --- agent/complete.go | 110 ---------------------------------------------- fs/handlers.go | 18 -------- fs/spec.go | 5 --- 3 files changed, 133 deletions(-) delete mode 100644 agent/complete.go diff --git a/agent/complete.go b/agent/complete.go deleted file mode 100644 index b79e636..0000000 --- a/agent/complete.go +++ /dev/null @@ -1,110 +0,0 @@ -package agent - -import ( - "context" - "fmt" - "os" - "strings" - - "ollie/backend" - "ollie/paths" -) - -// Complete performs a stateless one-shot code completion. -// -// TRANSITIONAL: This is an ephemeral agent — no history, no lifecycle, just -// prompt→completion. The intent is to unify this with the Agent struct such -// that one composes the other (a full Agent IS-A one-shot with state layered on). -func 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 == "" { - cfg := loadModelsConfig() - if model == "" && cfg.Completion.Model != "" { - model = cfg.Completion.Model - } - if backendName == "" && cfg.Completion.Backend != "" { - backendName = cfg.Completion.Backend - } - } - if model == "" || backendName == "" { - return "", fmt.Errorf("OLLIE_COMPLETE_MODEL and OLLIE_COMPLETE_BACKEND must be set (or configured in models.yaml)") - } - - const prefixMax = 12000 - const suffixMax = 1000 - if len(prefix) > prefixMax { - prefix = prefix[len(prefix)-prefixMax:] - } - if len(suffix) > suffixMax { - suffix = suffix[:suffixMax] - } - - 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) - - result, err := backend.Generate(context.Background(), backend.GenerateRequest{ - Prompt: prompt, - Backend: backendName, - Model: model, - }) - if err != nil { - return "", err - } - - result = stripCompletionNoise(result) - result = stripPrefixEcho(prefix, result) - return result, nil -} - -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 -} diff --git a/fs/handlers.go b/fs/handlers.go index 0c66396..546cf9b 100644 --- a/fs/handlers.go +++ b/fs/handlers.go @@ -117,24 +117,6 @@ func blockEventwait(_ HandlerCtx, cctx context.Context, base string) ([]byte, st return session.WaitEvent(cctx, base) } -func requestComplete(_ HandlerCtx, data []byte) ([]byte, error) { - 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(data, &req); err != nil { - req.Prefix = strings.TrimSpace(string(data)) - } - result, err := agent.Complete(req.CWD, req.FilePath, req.Prefix, req.Suffix, req.ExtraContext) - if err != nil { - return nil, err - } - return []byte(result + "\n"), nil -} - func requestGenerate(_ HandlerCtx, data []byte) ([]byte, error) { var req backend.GenerateRequest if err := json.Unmarshal(data, &req); err != nil { diff --git a/fs/spec.go b/fs/spec.go index 7632c3a..d5b6194 100644 --- a/fs/spec.go +++ b/fs/spec.go @@ -123,11 +123,6 @@ var treeSpec = DirNode("/", BlockOnce(blockEventwait), ), - FileNode("complete", 0666, - Doc("Code completion. Write JSON {file,prefix,suffix,context} or plain prefix. Read returns completion."), - Request(requestComplete), - ), - FileNode("generate", 0666, Doc("One-shot LLM generation. Write JSON {prompt,...} or plain text. Read returns result."), Request(requestGenerate),