Add Log command to Acme interface
Opens streaming log window that displays session chat history.
Window is named /AnviLLM/Log.{session-id-or-alias} and streams
log data continuously, marking window as clean after each write.
This commit is contained in:
parent
ab5f9705cd
commit
b47f6ba97d
|
|
@ -7,3 +7,4 @@ anvilweb
|
|||
.claude
|
||||
.kiro
|
||||
*.elc
|
||||
Assist
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ Type `Assist` in Acme and middle-click to open the `/AnviLLM/` session manager.
|
|||
|
||||
### Commands
|
||||
|
||||
**Main window** (`/AnviLLM/`) tag: `Get Attach Stop Restart Kill Alias Context Daemon Sandbox`
|
||||
**Main window** (`/AnviLLM/`) tag: `Get Attach Stop Restart Kill Alias Context Log Daemon Sandbox`
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
|
|
@ -217,6 +217,7 @@ Type `Assist` in Acme and middle-click to open the `/AnviLLM/` session manager.
|
|||
| `Attach <id>` | Open tmux terminal |
|
||||
| `Alias <id> <name>` | Name a session |
|
||||
| `Context <id>` | Edit context (prepended to prompts) |
|
||||
| `Log <id>` | View session log |
|
||||
| `Daemon` | Manage anvilsrv daemon (start/stop/status) |
|
||||
| `Sandbox` | Configure sandbox settings |
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ func main() {
|
|||
defer w.CloseFiles()
|
||||
|
||||
w.Name(windowName)
|
||||
w.Write("tag", []byte("Get Attach Stop Restart Kill Alias Context Daemon Sandbox "))
|
||||
w.Write("tag", []byte("Get Attach Stop Restart Kill Alias Context Log Daemon Sandbox "))
|
||||
refreshList(w)
|
||||
w.Ctl("clean")
|
||||
|
||||
|
|
@ -221,6 +221,19 @@ func main() {
|
|||
if err := openContextWindow(sess); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error opening context window: %v\n", err)
|
||||
}
|
||||
case "Log":
|
||||
if arg == "" {
|
||||
fmt.Fprintf(os.Stderr, "Usage: Log <session-id>\n")
|
||||
continue
|
||||
}
|
||||
sess, err := getSession(arg)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Session not found: %s\n", arg)
|
||||
continue
|
||||
}
|
||||
if err := openLogWindow(sess); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error opening log window: %v\n", err)
|
||||
}
|
||||
case "Sandbox":
|
||||
if err := openSandboxWindow(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error opening sandbox window: %v\n", err)
|
||||
|
|
@ -592,6 +605,57 @@ func openContextWindow(sess *SessionInfo) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func openLogWindow(sess *SessionInfo) error {
|
||||
go func() {
|
||||
displayName := sess.Alias
|
||||
if displayName == "" {
|
||||
displayName = sess.ID
|
||||
}
|
||||
|
||||
w, err := acme.New()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating log window: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer w.CloseFiles()
|
||||
|
||||
w.Name(fmt.Sprintf("/AnviLLM/Log.%s", displayName))
|
||||
w.Ctl("clean")
|
||||
|
||||
// Stream log using external command
|
||||
logPath := fmt.Sprintf("agent/%s/log", sess.ID)
|
||||
cmd := exec.Command("9p", "read", logPath)
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating pipe: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error starting 9p read: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Stream output to window
|
||||
buf := make([]byte, 8192)
|
||||
for {
|
||||
n, err := stdout.Read(buf)
|
||||
if n > 0 {
|
||||
w.Addr("$")
|
||||
w.Write("data", buf[:n])
|
||||
w.Ctl("clean")
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
cmd.Wait()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleContextWindow(w *acme.Win, sess *SessionInfo) {
|
||||
defer w.CloseFiles()
|
||||
|
||||
|
|
|
|||
Reference in New Issue