feat(tui-go): slash command menu in the chat input

Typing `/` as the first char of a chat line opens the command palette inline
(opencode-style), instead of typing a literal slash; mid-line `/` stays literal.
Factors openPalette() (shared with the `p` key) and advertises `/ cmds` in the
insert-mode footer when the line is empty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 09:35:34 +00:00
parent 9143d554f1
commit 85bfddf1c4
3 changed files with 66 additions and 3 deletions
+17 -3
View File
@@ -229,9 +229,7 @@ func (m Model) handleNormalKey(k tea.KeyMsg) (tea.Model, tea.Cmd) {
case "k":
m.navUp()
case "p":
m.overlay = OverlayPalette
m.paletteFilter = ""
m.paletteIndex = 0
m.openPalette()
case "e":
m.overlay = OverlayEventInspector
m.overlayEventIdx = 0
@@ -408,12 +406,28 @@ func (m Model) handleInsertKey(k tea.KeyMsg) (tea.Model, tea.Cmd) {
m.historyNext()
}
case tea.KeyRunes, tea.KeySpace:
// opencode-style slash commands: `/` as the first char of a chat line opens the
// command palette inline instead of typing a literal slash. Mid-line `/` is literal.
if m.inputMode == ModeRouter && m.inputBuffer == "" && string(k.Runes) == "/" {
m.editMode = ModeNormal
m.clearInput()
m.openPalette()
return m, nil
}
m.appendRunes(string(k.Runes))
m.syncFilter()
}
return m, nil
}
// openPalette opens the command palette with a cleared filter. Shared by the `p`
// normal-mode key and the inline `/` trigger in the chat input.
func (m *Model) openPalette() {
m.overlay = OverlayPalette
m.paletteFilter = ""
m.paletteIndex = 0
}
// beginIntent stashes the chosen workflow and switches to a text-entry prompt for the
// freeform request. Submitting sends StartSession(id, intent); an empty line starts with no
// intent (fixed-task workflows). Esc cancels.