diff --git a/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte b/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte
index 787d9ef4fc..b01e696df2 100644
--- a/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte
+++ b/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte
@@ -13,6 +13,7 @@
workspaceItemRegistry
} from './workspaceItems.svelte'
import { markdownProse } from '$lib/components/markdownProse'
+ import DisplayResult from '$lib/components/DisplayResult.svelte'
interface Props {
message: DisplayMessage
@@ -58,6 +59,20 @@
return rest === 0 ? `${minutes}m` : `${minutes}m ${rest}s`
}
+ const stepName = $derived(message.role === 'assistant' ? message.stepName : undefined)
+
+ // A flow step can return a file rather than text; the raw JSON would be
+ // unreadable, so hand it to the result viewer instead of the markdown renderer.
+ const s3Object = $derived.by(() => {
+ if (!message.content.startsWith('{')) return undefined
+ try {
+ const parsed = JSON.parse(message.content)
+ return parsed?.type === 'windmill_s3_object' && parsed?.s3 ? parsed : undefined
+ } catch {
+ return undefined
+ }
+ })
+
const candidatePaths = $derived(extractCandidatePaths(message.content))
const rendererPlugin = {
renderer: {
@@ -111,7 +126,13 @@
{/if}
-{#if message.content}
+{#if stepName}
+
{stepName}
+{/if}
+
+{#if s3Object}
+
+{:else if message.content}
diff --git a/frontend/src/lib/components/copilot/chat/shared.ts b/frontend/src/lib/components/copilot/chat/shared.ts
index b485be51b3..967d358166 100644
--- a/frontend/src/lib/components/copilot/chat/shared.ts
+++ b/frontend/src/lib/components/copilot/chat/shared.ts
@@ -629,6 +629,9 @@ export type AssistantDisplayMessage = BaseDisplayMessage & {
* would look like it is still streaming forever.
*/
streaming?: boolean
+ /** Flow step that produced this message, when the conversation is a flow run
+ * rather than a copilot turn. Rendered as a label above the content. */
+ stepName?: string
}
/**
diff --git a/frontend/src/lib/components/flows/conversations/FlowChat.svelte b/frontend/src/lib/components/flows/conversations/FlowChat.svelte
index 7966caa8c5..127e33dbc4 100644
--- a/frontend/src/lib/components/flows/conversations/FlowChat.svelte
+++ b/frontend/src/lib/components/flows/conversations/FlowChat.svelte
@@ -17,6 +17,8 @@
path: string
hideSidebar?: boolean
inputSchema?: Record
+ /** Wider centered column, for the full-page chat. */
+ wideLayout?: boolean
}
let {
@@ -25,7 +27,8 @@
useStreaming = false,
path,
hideSidebar = false,
- inputSchema = undefined
+ inputSchema = undefined,
+ wideLayout = false
}: Props = $props()
const flowEditorContext = getContext('FlowEditorContext')
@@ -72,5 +75,11 @@
{#if !hideSidebar}
{/if}
-
+
diff --git a/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte b/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte
index ab52d06102..8756353777 100644
--- a/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte
+++ b/frontend/src/lib/components/flows/conversations/FlowChatInterface.svelte
@@ -1,9 +1,10 @@