Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions src/renderer/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { DispatchLayout } from '@renderer/workspace/dispatch/DispatchLayout'
import { useAppStore } from '@renderer/app-state/hooks'
import { applyTheme } from '@renderer/app-state/settings/theme'
import { useKeybinds } from '@renderer/workspace/tile-tree/useKeybinds'
import { commandTargetSessionId } from '@renderer/workspace/hook/selectors/commandTargetSessionId'
import { useWorkspace } from '@renderer/workspace/workspaceStore'

// App — thin shell around the workspace hook.
Expand Down Expand Up @@ -260,6 +261,7 @@ export default function App() {
useKeybinds(workspace, onNewTabRequest, onResumeRequest, toggleCommandPalette)

const { state, activeTab } = workspace
const commandTargetId = commandTargetSessionId(workspace)
const buriedPromptMeta = buryPromptSessionId
? workspace.state.sessions[buryPromptSessionId] ?? null
: null
Expand Down Expand Up @@ -363,8 +365,8 @@ export default function App() {
{gitBarOpen && (
<GitBar
cwd={
activeTab
? workspace.state.sessions[activeTab.focusedSessionId]?.cwd ?? null
commandTargetId
? workspace.state.sessions[commandTargetId]?.cwd ?? null
: null
}
onClose={toggleGitBar}
Expand All @@ -374,45 +376,45 @@ export default function App() {
{worktreesBarOpen && (
<WorktreesBar
cwd={
activeTab
? workspace.state.sessions[activeTab.focusedSessionId]?.cwd ?? null
commandTargetId
? workspace.state.sessions[commandTargetId]?.cwd ?? null
: null
}
workspace={workspace}
onClose={toggleWorktreesBar}
/>
)}

{debugPanelOpen && activeTab && (
{debugPanelOpen && commandTargetId && (
<DebugPanel
sessionId={activeTab.focusedSessionId}
runtime={workspace.getRuntime(activeTab.focusedSessionId)}
kind={workspace.state.sessions[activeTab.focusedSessionId]?.kind ?? 'claude'}
sessionId={commandTargetId}
runtime={workspace.getRuntime(commandTargetId)}
kind={workspace.state.sessions[commandTargetId]?.kind ?? 'claude'}
onClose={toggleDebugPanel}
/>
)}

{feedDebugPanelOpen && activeTab && (
{feedDebugPanelOpen && commandTargetId && (
<FeedDebugPanel
sessionId={activeTab.focusedSessionId}
runtime={workspace.getRuntime(activeTab.focusedSessionId)}
kind={workspace.state.sessions[activeTab.focusedSessionId]?.kind ?? 'claude'}
sessionId={commandTargetId}
runtime={workspace.getRuntime(commandTargetId)}
kind={workspace.state.sessions[commandTargetId]?.kind ?? 'claude'}
onClose={toggleFeedDebugPanel}
/>
)}

{proxyDebugPanelOpen && activeTab && (
{proxyDebugPanelOpen && commandTargetId && (
<ProxyDebugPanel
sessionId={activeTab.focusedSessionId}
kind={workspace.state.sessions[activeTab.focusedSessionId]?.kind ?? 'claude'}
sessionId={commandTargetId}
kind={workspace.state.sessions[commandTargetId]?.kind ?? 'claude'}
onClose={toggleProxyDebugPanel}
/>
)}

{htmlDebugPanelOpen && activeTab && (
{htmlDebugPanelOpen && commandTargetId && (
<HtmlDebugPanel
sessionId={activeTab.focusedSessionId}
kind={workspace.state.sessions[activeTab.focusedSessionId]?.kind ?? 'claude'}
sessionId={commandTargetId}
kind={workspace.state.sessions[commandTargetId]?.kind ?? 'claude'}
onClose={toggleHtmlDebugPanel}
/>
)}
Expand Down
20 changes: 10 additions & 10 deletions src/renderer/src/features/command-palette/ui/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
updateCustomPromptTemplate,
type PromptTemplate,
} from '@renderer/features/prompt-templates/templates'
import { commandTargetSessionId } from '@renderer/workspace/hook/selectors/commandTargetSessionId'
import type { Workspace } from '@renderer/workspace/workspaceStore'

// CommandPalette — VS Code-style ⌘⇧P command menu.
Expand Down Expand Up @@ -167,8 +168,9 @@ export function CommandPalette({
const inputRef = useRef<HTMLInputElement>(null)
const listRef = useRef<HTMLDivElement>(null)

const focusedMeta = workspace.activeTab
? workspace.state.sessions[workspace.activeTab.focusedSessionId]
const focusedSessionId = commandTargetSessionId(workspace)
const focusedMeta = focusedSessionId
? workspace.state.sessions[focusedSessionId]
: null
const focusedCwd = focusedMeta?.cwd ?? null
const focusedProvider = focusedMeta?.kind ?? 'claude'
Expand Down Expand Up @@ -231,9 +233,9 @@ export function CommandPalette({
}, [])

const enterSavePromptTemplateMode = useCallback(() => {
const tab = workspace.activeTab
if (!tab) return
const draft = workspace.getRuntime(tab.focusedSessionId).draftInput.trim()
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return
const draft = workspace.getRuntime(sessionId).draftInput.trim()
if (!draft) return
setPromptTemplateForm({ id: null, title: '', body: draft })
setMode('save-prompt-template')
Expand Down Expand Up @@ -475,9 +477,8 @@ export function CommandPalette({

const executePromptTemplate = useCallback(
async (template: PromptTemplate) => {
const tab = workspace.activeTab
if (!tab) return
const sessionId = tab.focusedSessionId
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return

try {
const body = template.buildBody
Expand Down Expand Up @@ -508,8 +509,7 @@ export function CommandPalette({
const body = promptTemplateForm.body.trim()
if (!title || !body) return

const tab = workspace.activeTab
const sessionId = tab?.focusedSessionId ?? null
const sessionId = commandTargetSessionId(workspace)
const template = promptTemplateForm.id
? updateCustomPromptTemplate(promptTemplateForm.id, title, body)
: saveCustomPromptTemplate(title, body)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { CommandDef } from '@renderer/features/command-palette/types'
import { commandTargetSessionId } from '@renderer/workspace/hook/selectors/commandTargetSessionId'

// "Copy Assistant Message" — opens the picker on the focused pane.
// All navigation (Up/Down/Enter/Esc) is handled by useKeybinds when
Expand All @@ -11,11 +12,11 @@ export const copyAssistantCommands: CommandDef[] = [
id: 'copy-assistant-message',
title: 'Copy Assistant Message…',
keywords: ['copy', 'assistant', 'message', 'response', 'pick'],
when: ({ workspace }) => workspace.activeTab !== null,
when: ({ workspace }) => commandTargetSessionId(workspace) !== null,
run: ({ workspace }) => {
const tab = workspace.activeTab
if (!tab) return
workspace.pickerEnter(tab.focusedSessionId)
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return
workspace.pickerEnter(sessionId)
},
},
]
6 changes: 3 additions & 3 deletions src/renderer/src/features/debug/saveDebugBundle.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Workspace } from '@renderer/workspace/workspaceStore'
import type { SessionRuntime } from '@renderer/workspace/workspaceState'
import { sanitizeHtml } from '@renderer/lib/sanitizeHtml'
import { commandTargetSessionId } from '@renderer/workspace/hook/selectors/commandTargetSessionId'
import {
exportDebugTraceFiles,
recordHtmlTraceSnapshot,
Expand Down Expand Up @@ -368,9 +369,8 @@ export async function autosaveActiveAgentDebugBundles(
// this logic is reusable if we ever surface the command elsewhere
// (e.g. a keybinding or a right-click menu).
export async function runSaveDebugBundleCommand(workspace: Workspace): Promise<void> {
const tab = workspace.activeTab
if (!tab) return
const sessionId = tab.focusedSessionId
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return
const meta = workspace.state.sessions[sessionId]
const runtime = workspace.getRuntime(sessionId)
const kind = meta?.kind ?? 'claude'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { CommandDef } from '@renderer/features/command-palette/types'
import { commandTargetSessionId } from '@renderer/workspace/hook/selectors/commandTargetSessionId'
import type { Workspace } from '@renderer/workspace/workspaceStore'

function focusedAgentSessionId(workspace: Workspace): string | null {
const tab = workspace.activeTab
if (!tab) return null
const kind = workspace.state.sessions[tab.focusedSessionId]?.kind ?? 'claude'
return kind === 'terminal' ? null : tab.focusedSessionId
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return null
const kind = workspace.state.sessions[sessionId]?.kind ?? 'claude'
return kind === 'terminal' ? null : sessionId
}

export const promptTemplateCommands: CommandDef[] = [
Expand Down
24 changes: 12 additions & 12 deletions src/renderer/src/features/workspace/commands/paneCommands.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { extractLastAssistantText } from '@renderer/lib/copyAssistant'
import type { CommandDef } from '@renderer/features/command-palette/types'
import { commandTargetSessionId } from '@renderer/workspace/hook/selectors/commandTargetSessionId'

export const paneCommands: CommandDef[] = [
{
Expand Down Expand Up @@ -145,29 +146,29 @@ export const paneCommands: CommandDef[] = [
id: 'toggle-tail',
title: 'Tail',
getState: ({ workspace }) => {
const tab = workspace.activeTab
const tailMode = tab
? workspace.getRuntime(tab.focusedSessionId).tailMode
const sessionId = commandTargetSessionId(workspace)
const tailMode = sessionId
? workspace.getRuntime(sessionId).tailMode
: false
return {
label: tailMode ? 'On' : 'Off',
tone: tailMode ? 'accent' : 'neutral',
}
},
run: ({ workspace }) => {
const tab = workspace.activeTab
if (!tab) return
workspace.toggleTailMode(tab.focusedSessionId)
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return
workspace.toggleTailMode(sessionId)
},
},
{
id: 'jump-latest-message',
title: 'Jump to Latest Message',
shortcut: 'End',
when: ({ workspace }) => {
const tab = workspace.activeTab
if (!tab) return false
const kind = workspace.state.sessions[tab.focusedSessionId]?.kind ?? 'claude'
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return false
const kind = workspace.state.sessions[sessionId]?.kind ?? 'claude'
return kind !== 'terminal'
},
run: ({ workspace }) => {
Expand All @@ -178,9 +179,8 @@ export const paneCommands: CommandDef[] = [
id: 'copy-last-assistant',
title: 'Copy Last Response',
run: ({ workspace }) => {
const tab = workspace.activeTab
if (!tab) return
const sessionId = tab.focusedSessionId
const sessionId = commandTargetSessionId(workspace)
if (!sessionId) return
const runtime = workspace.getRuntime(sessionId)
const kind = workspace.state.sessions[sessionId]?.kind ?? 'claude'
const text = extractLastAssistantText(runtime.entries, kind)
Expand Down
Loading