fix(app): source composer cwd from agent state, not draft hook
The GitHub picker showed "No results found." for any running agent after
the first message was sent. useAgentInputDraft owned a local cwd state
that clear("sent") wiped to "", so the composer read cwd: "" even though
the agent's real cwd was correct on the wire.
Drop cwd ownership from the hook. Composer takes cwd as a prop sourced
by the parent — agentState.cwd for running agents, composerState.workingDir
for drafts, sourceDirectory for setup flows. The hook now persists only
{text, attachments}. Legacy persisted drafts with a cwd field still
hydrate; tagged COMPAT(draft-cwd) for removal after 2026-11-09.
Also moves attachment pills back inside the composer's bordered surface
via a new attachmentSlot prop on MessageInput, and shrinks pill height
from 48 to 32 — the subagents-track tuck previously had attachments
floating between it and the input.
Adds one Playwright spec asserting the draft-create-agent path submits
the workspace cwd.
This commit is contained in:
@@ -1541,7 +1541,6 @@ export function Composer({
|
||||
|
||||
<View style={styles.messageInputContainer}>
|
||||
{autocompletePopover}
|
||||
{attachmentPreviewList}
|
||||
|
||||
{/* MessageInput handles everything: text, dictation, attachments, all buttons */}
|
||||
<StableMessageInput
|
||||
@@ -1581,6 +1580,7 @@ export function Composer({
|
||||
onFocusChange={handleFocusChange}
|
||||
onHeightChange={onComposerHeightChange}
|
||||
inputWrapperStyle={inputWrapperStyle}
|
||||
attachmentSlot={attachmentPreviewList}
|
||||
/>
|
||||
<Combobox
|
||||
options={githubSearchOptions}
|
||||
@@ -1685,16 +1685,16 @@ const styles = StyleSheet.create((theme: Theme) => ({
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
imageThumbnail: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
width: 32,
|
||||
height: 32,
|
||||
},
|
||||
imageThumbnailPlaceholder: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
width: 32,
|
||||
height: 32,
|
||||
backgroundColor: theme.colors.surface2,
|
||||
},
|
||||
githubPillBody: {
|
||||
minHeight: 48,
|
||||
minHeight: 32,
|
||||
maxWidth: 260,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
|
||||
@@ -125,6 +125,8 @@ export interface MessageInputProps {
|
||||
onHeightChange?: (height: number) => void;
|
||||
/** Extra styles merged onto the input wrapper (e.g. elevated background). */
|
||||
inputWrapperStyle?: import("react-native").ViewStyle;
|
||||
/** Content rendered inside the bordered input surface, above the text input (e.g. attachment pills). */
|
||||
attachmentSlot?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface MessageInputRef {
|
||||
@@ -1094,6 +1096,7 @@ interface ResolvedMessageInputProps {
|
||||
onFocusChange: ((focused: boolean) => void) | undefined;
|
||||
onHeightChange: ((height: number) => void) | undefined;
|
||||
inputWrapperStyle: import("react-native").ViewStyle | undefined;
|
||||
attachmentSlot: React.ReactNode;
|
||||
}
|
||||
|
||||
function resolveMessageInputProps(props: MessageInputProps): ResolvedMessageInputProps {
|
||||
@@ -1133,6 +1136,7 @@ function resolveMessageInputProps(props: MessageInputProps): ResolvedMessageInpu
|
||||
onFocusChange: props.onFocusChange,
|
||||
onHeightChange: props.onHeightChange,
|
||||
inputWrapperStyle: props.inputWrapperStyle,
|
||||
attachmentSlot: props.attachmentSlot,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1180,6 +1184,7 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
|
||||
onFocusChange,
|
||||
onHeightChange,
|
||||
inputWrapperStyle,
|
||||
attachmentSlot,
|
||||
} = resolveMessageInputProps(props);
|
||||
const buttonIconSize = isWeb ? ICON_SIZE.md : ICON_SIZE.lg;
|
||||
const toast = useToast();
|
||||
@@ -1697,6 +1702,7 @@ export const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
|
||||
<View ref={rootRef} style={styles.container} testID="message-input-root">
|
||||
{/* Regular input */}
|
||||
<Animated.View ref={inputWrapperRef} style={inputWrapperCombinedStyle}>
|
||||
{attachmentSlot}
|
||||
{/* Text input */}
|
||||
<View style={styles.textInputScrollWrapper}>
|
||||
<ThemedTextInput
|
||||
|
||||
@@ -151,7 +151,6 @@ export function WorkspaceSetupDialog() {
|
||||
const isConnected = useHostRuntimeIsConnected(serverId);
|
||||
const chatDraft = useAgentInputDraft({
|
||||
draftKey: `workspace-setup:${serverId}:${sourceDirectory}`,
|
||||
initialCwd: sourceDirectory,
|
||||
composer: buildChatDraftComposerArgs({
|
||||
serverId,
|
||||
isConnected,
|
||||
@@ -393,7 +392,7 @@ export function WorkspaceSetupDialog() {
|
||||
onChangeText={chatDraft.setText}
|
||||
attachments={chatDraft.attachments}
|
||||
onChangeAttachments={chatDraft.setAttachments}
|
||||
cwd={chatDraft.cwd}
|
||||
cwd={sourceDirectory}
|
||||
clearDraft={chatDraft.clear}
|
||||
autoFocus
|
||||
commandDraftConfig={composerState?.commandDraftConfig}
|
||||
|
||||
Reference in New Issue
Block a user