From 69e5bd18d9434e6bd9f03da9633eddecb5924a34 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Mon, 13 Apr 2026 13:41:30 +0200 Subject: [PATCH] 9p: make ctl sync, guard non-stop commands when agent is running ctl is no longer in the async bucket. stop is always instant. Slash commands forwarded via Submit are synchronous for recognized commands. Unrecognized input is rejected with Rerror when the agent is running to prevent accidentally starting an agent turn. --- internal/p9/server.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/p9/server.go b/internal/p9/server.go index 6a1f966..92d83bd 100644 --- a/internal/p9/server.go +++ b/internal/p9/server.go @@ -754,7 +754,7 @@ func (s *Server) isAsyncWrite(path string) bool { return false } switch pathBase(path) { - case "prompt", "enqueue", "ctl": + case "prompt", "enqueue": return true } return false @@ -891,10 +891,17 @@ func (s *Server) handleWrite(path, input string) error { switch input { case "stop": sess.core.Interrupt(agent.ErrInterrupted) + return nil default: + // Forward as slash command. Submit handles it synchronously + // for recognized commands; unrecognized ones fall through to + // start an agent turn, which we must not do from ctl. + if sess.core.IsRunning() { + return fmt.Errorf("agent is running") + } sess.core.Submit(sess.ctx, "/"+input, publish) + return nil } - return nil case "backend": if sess.core.IsRunning() {