Skip to content

Commit d1d4206

Browse files
authored
Merge pull request #652 from dgageot/fix-517
Allow palette tools to run as /commands
2 parents 34e5b87 + 68cd9ac commit d1d4206

5 files changed

Lines changed: 84 additions & 65 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,9 @@ agents:
280280

281281
### Session Commands During CLI Usage
282282

283-
- `/exit` - End the session
284-
- `/reset` - Clear session history
285-
- `/usage` - Show token usage statistics
283+
- `/new` - Clear session history
286284
- `/compact` - Generate summary and compact session history
285+
- `/copy` - Show token usage statistics
287286
- `/eval` - Save evaluation data
288287

289288
## File Locations and Patterns

cmd/root/run.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ func runWithoutTUI(ctx context.Context, agentFilename string, rt runtime.Runtime
549549
return nil
550550
}
551551

552+
// TODO: This is a duplication of builtInSessionCommands() in pkg/tui/tui.go
552553
func runUserCommand(userInput string, sess *session.Session, rt runtime.Runtime, ctx context.Context) (bool, error) {
553554
yellow := color.New(color.FgYellow).SprintfFunc()
554555
switch userInput {
@@ -565,7 +566,7 @@ func runUserCommand(userInput string, sess *session.Session, rt runtime.Runtime,
565566
fmt.Printf("%s\n", yellow("Input tokens: %d", sess.InputTokens))
566567
fmt.Printf("%s\n", yellow("Output tokens: %d", sess.OutputTokens))
567568
return true, nil
568-
case "/reset":
569+
case "/new":
569570
// Reset session items
570571
sess.Messages = []session.Item{}
571572
return true, nil

pkg/tui/dialog/command_palette.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ type CommandExecuteMsg struct {
1919

2020
// Command represents a single command in the palette
2121
type Command struct {
22-
ID string
23-
Label string
24-
Description string
25-
Category string
26-
Execute func() tea.Cmd
22+
ID string
23+
Label string
24+
Description string
25+
Category string
26+
SlashCommand string
27+
Execute func() tea.Cmd
2728
}
2829

2930
// CommandCategory represents a category of commands

pkg/tui/page/chat/chat.go

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ type chatPage struct {
6767
title string
6868
app *app.App
6969

70-
history *history.History
70+
history *history.History
71+
sessionCommands []dialog.Command
7172

7273
// Cached layout dimensions
7374
chatHeight int
@@ -95,7 +96,7 @@ func defaultKeyMap() KeyMap {
9596
}
9697

9798
// New creates a new chat page
98-
func New(a *app.App) Page {
99+
func New(a *app.App, sessionCommands []dialog.Command) Page {
99100
ed := editor.New()
100101

101102
historyStore, err := history.New()
@@ -105,14 +106,15 @@ func New(a *app.App) Page {
105106
ed.SetHistory(historyStore)
106107

107108
return &chatPage{
108-
title: a.Title(),
109-
sidebar: sidebar.New(),
110-
messages: messages.New(a),
111-
editor: ed,
112-
focusedPanel: PanelEditor,
113-
app: a,
114-
keyMap: defaultKeyMap(),
115-
history: historyStore,
109+
title: a.Title(),
110+
sidebar: sidebar.New(),
111+
messages: messages.New(a),
112+
editor: ed,
113+
focusedPanel: PanelEditor,
114+
app: a,
115+
keyMap: defaultKeyMap(),
116+
history: historyStore,
117+
sessionCommands: sessionCommands,
116118
}
117119
}
118120

@@ -500,6 +502,14 @@ func (p *chatPage) processMessage(content string) tea.Cmd {
500502
case strings.HasPrefix(content, "!"):
501503
p.app.RunBangCommand(ctx, content[1:])
502504
case strings.HasPrefix(content, "/"):
505+
// Try builtin session command first
506+
for _, sessionCommand := range p.sessionCommands {
507+
if sessionCommand.SlashCommand == content && sessionCommand.Execute != nil {
508+
return sessionCommand.Execute()
509+
}
510+
}
511+
512+
// Then user-defined commands
503513
p.app.Run(ctx, p.msgCancel, p.app.ResolveCommand(ctx, content))
504514
default:
505515
p.app.Run(ctx, p.msgCancel, content)

pkg/tui/tui.go

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ func DefaultKeyMap() KeyMap {
7878
// New creates and initializes a new TUI application model
7979
func New(a *app.App) tea.Model {
8080
t := &appModel{
81-
chatPage: chatpage.New(a),
8281
keyMap: DefaultKeyMap(),
8382
dialog: dialog.New(),
8483
notification: notification.New(),
8584
application: a,
8685
}
8786

8887
t.statusBar = statusbar.New(t)
88+
t.chatPage = chatpage.New(a, t.builtInSessionCommands())
8989

9090
return t
9191
}
@@ -316,55 +316,63 @@ func toFullscreenView(content string) tea.View {
316316
return view
317317
}
318318

319+
func (a *appModel) builtInSessionCommands() []dialog.Command {
320+
return []dialog.Command{
321+
{
322+
ID: "session.new",
323+
Label: "New",
324+
SlashCommand: "/new",
325+
Description: "Start a new conversation",
326+
Category: "Session",
327+
Execute: func() tea.Cmd {
328+
a.application.NewSession()
329+
a.chatPage = chatpage.New(a.application, a.builtInSessionCommands())
330+
a.dialog = dialog.New()
331+
a.statusBar = statusbar.New(a.chatPage)
332+
333+
return tea.Batch(a.Init(), a.handleWindowResize(a.wWidth, a.wHeight))
334+
},
335+
},
336+
{
337+
ID: "session.compact",
338+
Label: "Compact",
339+
SlashCommand: "/compact",
340+
Description: "Summarize the current conversation",
341+
Category: "Session",
342+
Execute: func() tea.Cmd {
343+
return a.chatPage.CompactSession()
344+
},
345+
},
346+
{
347+
ID: "session.clipboard",
348+
Label: "Copy",
349+
SlashCommand: "/copy",
350+
Description: "Copy the current conversation to the clipboard",
351+
Category: "Session",
352+
Execute: func() tea.Cmd {
353+
return a.chatPage.CopySessionToClipboard()
354+
},
355+
},
356+
{
357+
ID: "session.eval",
358+
Label: "Eval",
359+
SlashCommand: "/eval",
360+
Description: "Create an evaluation report for the current conversation",
361+
Category: "Session",
362+
Execute: func() tea.Cmd {
363+
evalFile, _ := evaluation.Save(a.application.Session())
364+
return core.CmdHandler(notification.ShowMsg{Text: fmt.Sprintf("Eval saved to file %s", evalFile)})
365+
},
366+
},
367+
}
368+
}
369+
319370
// buildCommandCategories builds the list of command categories for the command palette
320371
func (a *appModel) buildCommandCategories(ctx context.Context) []dialog.CommandCategory {
321372
categories := []dialog.CommandCategory{
322373
{
323-
Name: "Session",
324-
Commands: []dialog.Command{
325-
{
326-
ID: "session.new",
327-
Label: "New ",
328-
Description: "Start a new conversation",
329-
Category: "Session",
330-
Execute: func() tea.Cmd {
331-
a.application.NewSession()
332-
a.chatPage = chatpage.New(a.application)
333-
a.dialog = dialog.New()
334-
a.statusBar = statusbar.New(a.chatPage)
335-
336-
return tea.Batch(a.Init(), a.handleWindowResize(a.wWidth, a.wHeight))
337-
},
338-
},
339-
{
340-
ID: "session.compact",
341-
Label: "Compact",
342-
Description: "Summarize the current conversation",
343-
Category: "Session",
344-
Execute: func() tea.Cmd {
345-
return a.chatPage.CompactSession()
346-
},
347-
},
348-
{
349-
ID: "session.clipboard",
350-
Label: "Copy",
351-
Description: "Copy the current conversation to the clipboard",
352-
Category: "Session",
353-
Execute: func() tea.Cmd {
354-
return a.chatPage.CopySessionToClipboard()
355-
},
356-
},
357-
{
358-
ID: "session.eval",
359-
Label: "Eval",
360-
Description: "Create an evaluation report for the current conversation",
361-
Category: "Session",
362-
Execute: func() tea.Cmd {
363-
evalFile, _ := evaluation.Save(a.application.Session())
364-
return core.CmdHandler(notification.ShowMsg{Text: fmt.Sprintf("Eval saved to file %s", evalFile)})
365-
},
366-
},
367-
},
374+
Name: "Session",
375+
Commands: a.builtInSessionCommands(),
368376
},
369377
}
370378

0 commit comments

Comments
 (0)