9p: add s/kill synthetic script
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d10bdf6fcc
commit
4ec6707bf9
|
|
@ -44,7 +44,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"9fans.net/go/plan9"
|
|
||||||
"ollie/pkg/agent"
|
"ollie/pkg/agent"
|
||||||
"ollie/pkg/backend"
|
"ollie/pkg/backend"
|
||||||
"ollie/pkg/config"
|
"ollie/pkg/config"
|
||||||
|
|
@ -52,6 +51,8 @@ import (
|
||||||
"ollie/pkg/paths"
|
"ollie/pkg/paths"
|
||||||
"ollie/pkg/tools"
|
"ollie/pkg/tools"
|
||||||
"ollie/pkg/tools/execute"
|
"ollie/pkg/tools/execute"
|
||||||
|
|
||||||
|
"9fans.net/go/plan9"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -59,7 +60,6 @@ const (
|
||||||
QTFile = plan9.QTFILE
|
QTFile = plan9.QTFILE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// session holds all state for one ollie agent session.
|
// session holds all state for one ollie agent session.
|
||||||
type session struct {
|
type session struct {
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
@ -74,7 +74,6 @@ type session struct {
|
||||||
chatOffset int // byte position of chat EOF immediately before last prompt submit
|
chatOffset int // byte position of chat EOF immediately before last prompt submit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// appendChat appends data to the session's chat log and bumps the Qid version.
|
// appendChat appends data to the session's chat log and bumps the Qid version.
|
||||||
func (sess *session) appendChat(data []byte) {
|
func (sess *session) appendChat(data []byte) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
|
|
@ -573,8 +572,8 @@ func (s *Server) read(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// s/new, s/idx, and s/ls are served from the session store.
|
// s/new, s/idx, s/kill, and s/ls are served from the session store.
|
||||||
if path == "/s/new" || path == "/s/idx" || path == "/s/ls" {
|
if path == "/s/new" || path == "/s/idx" || path == "/s/ls" || path == "/s/kill" {
|
||||||
plog.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
|
plog.Debug("Tread path=%q offset=%d count=%d", path, fc.Offset, fc.Count)
|
||||||
content, err := s.sessionStore.Get(pathBase(path))
|
content, err := s.sessionStore.Get(pathBase(path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -709,7 +708,6 @@ func (s *Server) read(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
|
||||||
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: 0}
|
return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// readSlice serves a byte slice at the requested offset/count.
|
// readSlice serves a byte slice at the requested offset/count.
|
||||||
func (s *Server) readSlice(fc *plan9.Fcall, content []byte) *plan9.Fcall {
|
func (s *Server) readSlice(fc *plan9.Fcall, content []byte) *plan9.Fcall {
|
||||||
var data []byte
|
var data []byte
|
||||||
|
|
@ -728,7 +726,6 @@ func (s *Server) helpPath() string {
|
||||||
return paths.CfgDir() + "/help.md"
|
return paths.CfgDir() + "/help.md"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *Server) write(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
|
func (s *Server) write(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
|
||||||
cs.mu.Lock()
|
cs.mu.Lock()
|
||||||
f, ok := cs.fids[fc.Fid]
|
f, ok := cs.fids[fc.Fid]
|
||||||
|
|
@ -1208,8 +1205,6 @@ func (s *Server) killSession(id string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// formatEvent converts an agent Event to bytes for appending to the chat log.
|
// formatEvent converts an agent Event to bytes for appending to the chat log.
|
||||||
// Output matches ollie-tui's MakeOutputFn so the chat file looks identical to
|
// Output matches ollie-tui's MakeOutputFn so the chat file looks identical to
|
||||||
// what appears in the TUI chat pane.
|
// what appears in the TUI chat pane.
|
||||||
|
|
@ -1458,7 +1453,7 @@ func (s *Server) makeStat(path string) plan9.Dir {
|
||||||
default:
|
default:
|
||||||
if path == "/backends" || path == "/help" || path == "/s/idx" {
|
if path == "/backends" || path == "/help" || path == "/s/idx" {
|
||||||
mode = 0444
|
mode = 0444
|
||||||
} else if path == "/s/ls" {
|
} else if path == "/s/ls" || path == "/s/kill" {
|
||||||
mode = 0555
|
mode = 0555
|
||||||
} else if path == "/s/new" {
|
} else if path == "/s/new" {
|
||||||
mode = 0666
|
mode = 0666
|
||||||
|
|
@ -1533,7 +1528,7 @@ func (s *Server) makeStat(path string) plan9.Dir {
|
||||||
// that check stat before reading (cat, 9pfuse, etc.) see non-zero size.
|
// that check stat before reading (cat, 9pfuse, etc.) see non-zero size.
|
||||||
if dir.Length == 0 && !isDir {
|
if dir.Length == 0 && !isDir {
|
||||||
switch {
|
switch {
|
||||||
case path == "/s/new" || path == "/s/idx" || path == "/s/ls":
|
case path == "/s/new" || path == "/s/idx" || path == "/s/ls" || path == "/s/kill":
|
||||||
if content, err := s.sessionStore.Get(base); err == nil {
|
if content, err := s.sessionStore.Get(base); err == nil {
|
||||||
dir.Length = uint64(len(content))
|
dir.Length = uint64(len(content))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ func (s *SessionStore) List() ([]os.DirEntry, error) {
|
||||||
syntheticEntry("new", 0666),
|
syntheticEntry("new", 0666),
|
||||||
syntheticEntry("idx", 0444),
|
syntheticEntry("idx", 0444),
|
||||||
syntheticEntry("ls", 0555),
|
syntheticEntry("ls", 0555),
|
||||||
|
syntheticEntry("kill", 0555),
|
||||||
}
|
}
|
||||||
s.srv.mu.RLock()
|
s.srv.mu.RLock()
|
||||||
for id := range s.srv.sessions {
|
for id := range s.srv.sessions {
|
||||||
|
|
@ -35,6 +36,8 @@ func (s *SessionStore) Stat(name string) (os.FileInfo, error) {
|
||||||
return &syntheticFileInfo{name: "idx", mode: 0444}, nil
|
return &syntheticFileInfo{name: "idx", mode: 0444}, nil
|
||||||
case "ls":
|
case "ls":
|
||||||
return &syntheticFileInfo{name: "ls", mode: 0555}, nil
|
return &syntheticFileInfo{name: "ls", mode: 0555}, nil
|
||||||
|
case "kill":
|
||||||
|
return &syntheticFileInfo{name: "kill", mode: 0555}, nil
|
||||||
}
|
}
|
||||||
s.srv.mu.RLock()
|
s.srv.mu.RLock()
|
||||||
_, ok := s.srv.sessions[name]
|
_, ok := s.srv.sessions[name]
|
||||||
|
|
@ -52,7 +55,9 @@ func (s *SessionStore) Get(name string) ([]byte, error) {
|
||||||
case "idx":
|
case "idx":
|
||||||
return s.index(), nil
|
return s.index(), nil
|
||||||
case "ls":
|
case "ls":
|
||||||
return []byte("#!/usr/bin/env bash\ncat ${OLLIE:-$HOME/mnt/ollie}/s/idx\n"), nil
|
return []byte("#!/usr/bin/env bash\ncat ${OLLIE}/s/idx\n"), nil
|
||||||
|
case "kill":
|
||||||
|
return []byte("#!/usr/bin/env bash\nrm -r ${OLLIE}/s/$1\n"), nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%s: not a readable file", name)
|
return nil, fmt.Errorf("%s: not a readable file", name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Reference in New Issue