From deefb540788759333aca313738679f117a708788 Mon Sep 17 00:00:00 2001 From: Benjamin Shafii Date: Tue, 3 Feb 2026 12:26:31 -0800 Subject: [PATCH] fix: enable attachments in remote sessions --- .../app/src/app/components/session/composer.tsx | 13 ++++++++----- packages/app/src/app/pages/session.tsx | 13 +++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/app/src/app/components/session/composer.tsx b/packages/app/src/app/components/session/composer.tsx index e949e39e..5aab723f 100644 --- a/packages/app/src/app/components/session/composer.tsx +++ b/packages/app/src/app/components/session/composer.tsx @@ -53,6 +53,8 @@ type ComposerProps = { recentFiles: string[]; searchFiles: (query: string) => Promise; isRemoteWorkspace: boolean; + attachmentsEnabled: boolean; + attachmentsDisabledReason: string | null; }; const MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024; @@ -274,7 +276,7 @@ export default function Composer(props: ComposerProps) { const [history, setHistory] = createSignal({ prompt: [] as ComposerDraft[], shell: [] as ComposerDraft[] }); const [variantMenuOpen, setVariantMenuOpen] = createSignal(false); const activeVariant = createMemo(() => props.modelVariant ?? "none"); - const attachmentsDisabled = createMemo(() => props.isRemoteWorkspace); + const attachmentsDisabled = createMemo(() => !props.attachmentsEnabled); onMount(() => { queueMicrotask(() => focusEditorEnd()); @@ -550,8 +552,8 @@ export default function Composer(props: ComposerProps) { }; const addAttachments = async (files: File[]) => { - if (props.isRemoteWorkspace) { - props.onToast("Attachments are unavailable in remote workspaces."); + if (attachmentsDisabled()) { + props.onToast(props.attachmentsDisabledReason ?? "Attachments are unavailable."); return; } const next: ComposerAttachment[] = []; @@ -813,7 +815,8 @@ export default function Composer(props: ComposerProps) { }`} onDrop={handleDrop} onDragOver={(event: DragEvent) => { - if (!props.isRemoteWorkspace) event.preventDefault(); + if (attachmentsDisabled()) return; + event.preventDefault(); }} > @@ -1169,7 +1172,7 @@ export default function Composer(props: ComposerProps) { disabled={attachmentsDisabled()} title={ attachmentsDisabled() - ? "Attachments are unavailable in remote workspaces." + ? props.attachmentsDisabledReason ?? "Attachments are unavailable." : "Attach files" } > diff --git a/packages/app/src/app/pages/session.tsx b/packages/app/src/app/pages/session.tsx index 9343b24c..3c04bcb5 100644 --- a/packages/app/src/app/pages/session.tsx +++ b/packages/app/src/app/pages/session.tsx @@ -186,6 +186,17 @@ export default function SessionView(props: SessionViewProps) { const commandNeedsDetails = (command: { template: string }) => COMMAND_ARGS_RE.test(command.template); const agentLabel = createMemo(() => props.selectedSessionAgent ?? "Default agent"); + const attachmentsEnabled = createMemo(() => { + if (props.activeWorkspaceDisplay.workspaceType !== "remote") return true; + return props.openworkServerStatus === "connected"; + }); + const attachmentsDisabledReason = createMemo(() => { + if (attachmentsEnabled()) return null; + if (props.openworkServerStatus === "limited") { + return "Add a server token to attach files."; + } + return "Connect to OpenWork server to attach files."; + }); const isNearBottom = (el: HTMLElement, threshold = 80) => { const distance = el.scrollHeight - el.scrollTop - el.clientHeight; @@ -1534,6 +1545,8 @@ export default function SessionView(props: SessionViewProps) { recentFiles={props.workingFiles} searchFiles={props.searchFiles} isRemoteWorkspace={props.activeWorkspaceDisplay.workspaceType === "remote"} + attachmentsEnabled={attachmentsEnabled()} + attachmentsDisabledReason={attachmentsDisabledReason()} /> 0}>