mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-22 18:24:21 +01:00
feat: toggle tool details visible
This commit is contained in:
@@ -202,6 +202,7 @@ export namespace Config {
|
||||
session_interrupt: z.string().optional().default("esc").describe("Interrupt current session"),
|
||||
session_compact: z.string().optional().default("<leader>c").describe("Compact the session"),
|
||||
tool_details: z.string().optional().default("<leader>d").describe("Toggle tool details"),
|
||||
thinking_blocks: z.string().optional().default("<leader>b").describe("Toggle thinking blocks"),
|
||||
model_list: z.string().optional().default("<leader>m").describe("List available models"),
|
||||
theme_list: z.string().optional().default("<leader>t").describe("List available themes"),
|
||||
file_list: z.string().optional().default("<leader>f").describe("List files"),
|
||||
|
||||
@@ -1007,7 +1007,7 @@ export namespace Session {
|
||||
async process(stream: StreamTextResult<Record<string, AITool>, never>) {
|
||||
try {
|
||||
let currentText: MessageV2.TextPart | undefined
|
||||
// let reasoningMap: Record<string, MessageV2.ReasoningPart> = {}
|
||||
let reasoningMap: Record<string, MessageV2.ReasoningPart> = {}
|
||||
|
||||
for await (const value of stream.fullStream) {
|
||||
log.info("part", {
|
||||
@@ -1017,7 +1017,6 @@ export namespace Session {
|
||||
case "start":
|
||||
break
|
||||
|
||||
/*
|
||||
case "reasoning-start":
|
||||
if (value.id in reasoningMap) {
|
||||
continue
|
||||
@@ -1055,7 +1054,6 @@ export namespace Session {
|
||||
delete reasoningMap[value.id]
|
||||
}
|
||||
break
|
||||
*/
|
||||
|
||||
case "tool-input-start":
|
||||
const part = await updatePart({
|
||||
|
||||
@@ -32,6 +32,8 @@ type State struct {
|
||||
MessagesRight bool `toml:"messages_right"`
|
||||
SplitDiff bool `toml:"split_diff"`
|
||||
MessageHistory []Prompt `toml:"message_history"`
|
||||
ShowToolDetails *bool `toml:"show_tool_details"`
|
||||
ShowThinkingBlocks *bool `toml:"show_thinking_blocks"`
|
||||
}
|
||||
|
||||
func NewState() *State {
|
||||
|
||||
@@ -119,6 +119,7 @@ const (
|
||||
SessionCompactCommand CommandName = "session_compact"
|
||||
SessionExportCommand CommandName = "session_export"
|
||||
ToolDetailsCommand CommandName = "tool_details"
|
||||
ThinkingBlocksCommand CommandName = "thinking_blocks"
|
||||
ModelListCommand CommandName = "model_list"
|
||||
AgentListCommand CommandName = "agent_list"
|
||||
ModelCycleRecentCommand CommandName = "model_cycle_recent"
|
||||
@@ -245,6 +246,12 @@ func LoadFromConfig(config *opencode.Config) CommandRegistry {
|
||||
Keybindings: parseBindings("<leader>d"),
|
||||
Trigger: []string{"details"},
|
||||
},
|
||||
{
|
||||
Name: ThinkingBlocksCommand,
|
||||
Description: "toggle thinking blocks",
|
||||
Keybindings: parseBindings("<leader>b"),
|
||||
Trigger: []string{"thinking"},
|
||||
},
|
||||
{
|
||||
Name: ModelListCommand,
|
||||
Description: "list models",
|
||||
|
||||
@@ -33,6 +33,7 @@ type MessagesComponent interface {
|
||||
HalfPageUp() (tea.Model, tea.Cmd)
|
||||
HalfPageDown() (tea.Model, tea.Cmd)
|
||||
ToolDetailsVisible() bool
|
||||
ThinkingBlocksVisible() bool
|
||||
GotoTop() (tea.Model, tea.Cmd)
|
||||
GotoBottom() (tea.Model, tea.Cmd)
|
||||
CopyLastMessage() (tea.Model, tea.Cmd)
|
||||
@@ -49,6 +50,7 @@ type messagesComponent struct {
|
||||
cache *PartCache
|
||||
loading bool
|
||||
showToolDetails bool
|
||||
showThinkingBlocks bool
|
||||
rendering bool
|
||||
dirty bool
|
||||
tail bool
|
||||
@@ -94,6 +96,7 @@ func (s selection) coords(offset int) *selection {
|
||||
}
|
||||
|
||||
type ToggleToolDetailsMsg struct{}
|
||||
type ToggleThinkingBlocksMsg struct{}
|
||||
|
||||
func (m *messagesComponent) Init() tea.Cmd {
|
||||
return tea.Batch(m.viewport.Init())
|
||||
@@ -160,7 +163,12 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m, m.renderView()
|
||||
case ToggleToolDetailsMsg:
|
||||
m.showToolDetails = !m.showToolDetails
|
||||
return m, m.renderView()
|
||||
m.app.State.ShowToolDetails = &m.showToolDetails
|
||||
return m, tea.Batch(m.renderView(), m.app.SaveState())
|
||||
case ToggleThinkingBlocksMsg:
|
||||
m.showThinkingBlocks = !m.showThinkingBlocks
|
||||
m.app.State.ShowThinkingBlocks = &m.showThinkingBlocks
|
||||
return m, tea.Batch(m.renderView(), m.app.SaveState())
|
||||
case app.SessionLoadedMsg, app.SessionClearedMsg:
|
||||
m.cache.Clear()
|
||||
m.tail = true
|
||||
@@ -561,10 +569,11 @@ func (m *messagesComponent) renderView() tea.Cmd {
|
||||
if reverted {
|
||||
continue
|
||||
}
|
||||
text := "..."
|
||||
if part.Text != "" {
|
||||
text = part.Text
|
||||
if !m.showThinkingBlocks {
|
||||
continue
|
||||
}
|
||||
if part.Text != "" {
|
||||
text := part.Text
|
||||
content = renderText(
|
||||
m.app,
|
||||
message.Info,
|
||||
@@ -589,6 +598,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
|
||||
hasContent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch err := casted.Error.AsUnion().(type) {
|
||||
case nil:
|
||||
@@ -1006,6 +1016,10 @@ func (m *messagesComponent) ToolDetailsVisible() bool {
|
||||
return m.showToolDetails
|
||||
}
|
||||
|
||||
func (m *messagesComponent) ThinkingBlocksVisible() bool {
|
||||
return m.showThinkingBlocks
|
||||
}
|
||||
|
||||
func (m *messagesComponent) GotoTop() (tea.Model, tea.Cmd) {
|
||||
m.viewport.GotoTop()
|
||||
return m, nil
|
||||
@@ -1202,10 +1216,22 @@ func NewMessagesComponent(app *app.App) MessagesComponent {
|
||||
vp.MouseWheelDelta = 4
|
||||
}
|
||||
|
||||
// Default to showing tool details, hidden thinking blocks
|
||||
showToolDetails := true
|
||||
if app.State.ShowToolDetails != nil {
|
||||
showToolDetails = *app.State.ShowToolDetails
|
||||
}
|
||||
|
||||
showThinkingBlocks := false
|
||||
if app.State.ShowThinkingBlocks != nil {
|
||||
showThinkingBlocks = *app.State.ShowThinkingBlocks
|
||||
}
|
||||
|
||||
return &messagesComponent{
|
||||
app: app,
|
||||
viewport: vp,
|
||||
showToolDetails: true,
|
||||
showToolDetails: showToolDetails,
|
||||
showThinkingBlocks: showThinkingBlocks,
|
||||
cache: NewPartCache(),
|
||||
tail: true,
|
||||
}
|
||||
|
||||
@@ -1142,6 +1142,13 @@ func (a Model) executeCommand(command commands.Command) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
cmds = append(cmds, util.CmdHandler(chat.ToggleToolDetailsMsg{}))
|
||||
cmds = append(cmds, toast.NewInfoToast(message))
|
||||
case commands.ThinkingBlocksCommand:
|
||||
message := "Thinking blocks are now visible"
|
||||
if a.messages.ThinkingBlocksVisible() {
|
||||
message = "Thinking blocks are now hidden"
|
||||
}
|
||||
cmds = append(cmds, util.CmdHandler(chat.ToggleThinkingBlocksMsg{}))
|
||||
cmds = append(cmds, toast.NewInfoToast(message))
|
||||
case commands.ModelListCommand:
|
||||
modelDialog := dialog.NewModelDialog(a.app)
|
||||
a.modal = modelDialog
|
||||
|
||||
@@ -136,13 +136,14 @@
|
||||
flex-grow: 1;
|
||||
max-width: var(--md-tool-width);
|
||||
|
||||
& > [data-component="assistant-reasoning-markdown"] {
|
||||
[data-component="assistant-reasoning-markdown"] {
|
||||
align-self: flex-start;
|
||||
font-size: 0.875rem;
|
||||
border: 1px solid var(--sl-color-blue-high);
|
||||
padding: 0.5rem calc(0.5rem + 3px);
|
||||
border-radius: 0.25rem;
|
||||
position: relative;
|
||||
margin-top: 0.5rem;
|
||||
|
||||
[data-component="copy-button"] {
|
||||
top: 0.5rem;
|
||||
|
||||
@@ -152,18 +152,23 @@ export function Part(props: PartProps) {
|
||||
)}
|
||||
{` | ${props.message.modelID}`}
|
||||
{props.message.mode && (
|
||||
<span style={{ "font-weight": "bold", color: "var(--sl-color-accent)" }}>
|
||||
{` | ${props.message.mode}`}
|
||||
</span>
|
||||
<span style={{ color: "var(--sl-color-accent)" }}>{` | ${props.message.mode}`}</span>
|
||||
)}
|
||||
</Footer>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{props.message.role === "assistant" && props.part.type === "reasoning" && (
|
||||
<div data-component="tool">
|
||||
<div data-component="tool-title">
|
||||
<span data-slot="name">Thinking</span>
|
||||
</div>
|
||||
<div data-component="assistant-reasoning">
|
||||
<ResultsButton showCopy="Show details" hideCopy="Hide details">
|
||||
<div data-component="assistant-reasoning-markdown">
|
||||
<ContentMarkdown expand={props.last} text={props.part.text || "Thinking..."} />
|
||||
<ContentMarkdown expand text={props.part.text || "Thinking..."} />
|
||||
</div>
|
||||
</ResultsButton>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -182,9 +187,7 @@ export function Part(props: PartProps) {
|
||||
)}
|
||||
{` | ${props.message.modelID}`}
|
||||
{props.message.mode && (
|
||||
<span style={{ "font-weight": "bold", color: "var(--sl-color-accent)" }}>
|
||||
{` | ${props.message.mode}`}
|
||||
</span>
|
||||
<span style={{ color: "var(--sl-color-accent)" }}>{` | ${props.message.mode}`}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user