diff --git a/src/renderer/components/ChatPane.tsx b/src/renderer/components/ChatPane.tsx index e9c6ee5..872aa97 100644 --- a/src/renderer/components/ChatPane.tsx +++ b/src/renderer/components/ChatPane.tsx @@ -10,7 +10,7 @@ import { PlanReviewBanner } from '@renderer/components/chat/PlanReviewBanner'; import { McpAuthBanner } from '@renderer/components/chat/McpAuthBanner'; import { UserInputBanner } from '@renderer/components/chat/UserInputBanner'; import { InlineApprovalPill, InlineGitPill, InlineModelPill, InlineTerminalPill, InlineThinkingPill, InlineToolsPill } from '@renderer/components/chat/InlinePills'; -import { InlinePromptPill } from '@renderer/components/chat/InlinePromptPill'; +import { InlinePromptPill, type ArmedPrompt } from '@renderer/components/chat/InlinePromptPill'; import { ThinkingDots } from '@renderer/components/chat/ThinkingDots'; import { ThinkingProcess } from '@renderer/components/chat/ThinkingProcess'; import { SubagentActivityList } from '@renderer/components/chat/SubagentActivityCard'; @@ -193,6 +193,7 @@ export function ChatPane({ const canSubmitInput = hasComposerContent && !isComposerDisabled; const [pendingAttachments, setPendingAttachments] = useState([]); const promptFiles = useMemo(() => project.customization?.promptFiles ?? [], [project.customization?.promptFiles]); + const [armedPrompt, setArmedPrompt] = useState(null); const toolSelection = useMemo(() => resolveSessionToolingSelection(session), [session]); const mcpServers = toolingSettings.mcpServers; @@ -232,13 +233,24 @@ export function ChatPane({ setIsResolvingApproval(false); setIsUpdatingSessionModelConfig(false); setEditingMessageId(undefined); + setArmedPrompt(null); }, [session.id]); function handleComposerSubmit(content: string) { const attachments = pendingAttachments.length > 0 ? [...pendingAttachments] : undefined; const messageMode: MessageMode | undefined = isSessionBusy ? 'immediate' : undefined; setPendingAttachments([]); - void onSend(content, attachments, messageMode); + + if (armedPrompt) { + const invocation = { ...armedPrompt.invocation }; + if (content.trim()) { + invocation.resolvedPrompt = `${invocation.resolvedPrompt}\n\n${content.trim()}`; + } + setArmedPrompt(null); + void onSend('', attachments, messageMode, invocation); + } else { + void onSend(content, attachments, messageMode); + } } const handleCopyMessage = useCallback((content: string) => { @@ -747,21 +759,23 @@ export function ChatPane({ onContentChange={setHasComposerContent} onSubmit={handleComposerSubmit} placeholder={ - pendingApproval - ? 'Awaiting approval...' - : pendingUserInput - ? 'Awaiting your input above...' - : pendingPlanReview - ? 'Review the plan above...' - : pendingMcpAuth - ? 'MCP server requires authentication...' - : isSessionBusy - ? 'Steer the agent (sends immediately)...' - : isUpdatingSessionModelConfig - ? 'Saving model settings...' - : isPlanMode - ? 'Describe what to plan...' - : 'Message...' + armedPrompt?.prompt.argumentHint + ? armedPrompt.prompt.argumentHint + : pendingApproval + ? 'Awaiting approval...' + : pendingUserInput + ? 'Awaiting your input above...' + : pendingPlanReview + ? 'Review the plan above...' + : pendingMcpAuth + ? 'MCP server requires authentication...' + : isSessionBusy + ? 'Steer the agent (sends immediately)...' + : isUpdatingSessionModelConfig + ? 'Saving model settings...' + : isPlanMode + ? 'Describe what to plan...' + : 'Message...' } > {/* Bottom action bar: left = shortcuts, right = buttons */} @@ -785,7 +799,10 @@ export function ChatPane({ )} {!isScratchpad && promptFiles.length > 0 && ( setArmedPrompt(null)} onSubmit={(promptInvocation) => void onSend('', undefined, undefined, promptInvocation)} promptFiles={promptFiles} /> @@ -847,9 +864,9 @@ export function ChatPane({ {/* Send / Stop / Steer button */} + {armedPrompt ? ( + + ) : ( + + )} {open && !disabled && (
)} + {prompt.model && ( + + {prompt.model} + + )}
{prompt.description && (
@@ -163,6 +213,11 @@ function PromptList({ {prompt.tools.length} tool{prompt.tools.length === 1 ? '' : 's'} )} + {prompt.argumentHint && ( + + hint: {prompt.argumentHint} + + )} {prompt.variables.map((v) => ( ))}
+ {prompt.sourcePath.startsWith('..') && ( +
+ {formatPromptSourcePath(prompt.sourcePath)} +
+ )} ))} @@ -206,8 +266,15 @@ function PromptVariableForm({
-
- {prompt.name} +
+ + {prompt.name} + + {prompt.model && ( + + {prompt.model} + + )}
{prompt.description && (
{prompt.description}
@@ -238,7 +305,7 @@ function PromptVariableForm({ type="button" > - Send prompt + {prompt.argumentHint ? 'Arm prompt' : 'Send prompt'}
);