termui: add terminal title updates based on sketch slug
Inspired by a conversation with anutron.
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: sdc02f5e60c8356b6k
diff --git a/termui/termui.go b/termui/termui.go
index af6376d..c0a8bc7 100644
--- a/termui/termui.go
+++ b/termui/termui.go
@@ -119,6 +119,9 @@
// Pending message count, for graceful shutdown
messageWaitGroup sync.WaitGroup
+
+ currentSlug string
+ titlePushed bool
}
type chatMessage struct {
@@ -157,7 +160,7 @@
return nil
}
-func (ui *TermUI) LogToolUse(resp *loop.AgentMessage) {
+func (ui *TermUI) HandleToolUse(resp *loop.AgentMessage) {
inputData := map[string]any{}
if err := json.Unmarshal([]byte(resp.ToolInput), &inputData); err != nil {
ui.AppendSystemMessage("error: %v", err)
@@ -169,6 +172,12 @@
return
}
ui.AppendSystemMessage("%s\n", buf.String())
+
+ if resp.ToolName == "set-slug" {
+ if slug, ok := inputData["slug"].(string); ok {
+ ui.updateTitleWithSlug(slug)
+ }
+ }
}
func (ui *TermUI) receiveMessagesLoop(ctx context.Context) {
@@ -195,7 +204,7 @@
case loop.AgentMessageType:
ui.AppendChatMessage(chatMessage{thinking: thinking, idx: resp.Idx, sender: "🕴️ ", content: resp.Content})
case loop.ToolUseMessageType:
- ui.LogToolUse(resp)
+ ui.HandleToolUse(resp)
case loop.ErrorMessageType:
ui.AppendSystemMessage("❌ %s", resp.Content)
case loop.BudgetMessageType:
@@ -411,7 +420,7 @@
ui.trm = term.NewTerminal(ui.stdin, "")
width, height, err := term.GetSize(int(ui.stdin.Fd()))
if err != nil {
- return fmt.Errorf("Error getting terminal size: %v\n", err)
+ return fmt.Errorf("get terminal size: %v", err)
}
ui.trm.SetSize(width, height)
// Handle terminal resizes...
@@ -432,6 +441,8 @@
}()
ui.updatePrompt(false)
+ ui.pushTerminalTitle()
+ ui.setTerminalTitle("sketch")
// This is the only place where we should call fe.trm.Write:
go func() {
@@ -475,6 +486,8 @@
func (ui *TermUI) RestoreOldState() error {
ui.mu.Lock()
defer ui.mu.Unlock()
+ ui.setTerminalTitle("")
+ ui.popTerminalTitle()
return term.Restore(int(ui.stdin.Fd()), ui.oldState)
}
@@ -555,3 +568,34 @@
}
return ""
}
+
+// pushTerminalTitle pushes the current terminal title onto the title stack
+// Only works on xterm-compatible terminals, but does no harm elsewhere
+func (ui *TermUI) pushTerminalTitle() {
+ fmt.Fprintf(ui.stderr, "\033[22;0t")
+ ui.titlePushed = true
+}
+
+// popTerminalTitle pops the terminal title from the title stack
+func (ui *TermUI) popTerminalTitle() {
+ if ui.titlePushed {
+ fmt.Fprintf(ui.stderr, "\033[23;0t")
+ ui.titlePushed = false
+ }
+}
+
+func (ui *TermUI) setTerminalTitle(title string) {
+ fmt.Fprintf(ui.stderr, "\033]0;%s\007", title)
+}
+
+// updateTitleWithSlug updates the terminal title with slug slug
+func (ui *TermUI) updateTitleWithSlug(slug string) {
+ ui.mu.Lock()
+ defer ui.mu.Unlock()
+ ui.currentSlug = slug
+ title := "sketch"
+ if slug != "" {
+ title = fmt.Sprintf("sketch: %s", slug)
+ }
+ ui.setTerminalTitle(title)
+}