Skip to content

Commit 9b7a8a8

Browse files
authored
Add overlay and disable inputs while copilot is streaming, fix number… (#1243)
* Add overlay and disable inputs while copilot is streaming, fix numbering on ship modal, add blur to modal overlay * Add missed component * Set is streaming to false when copilot unmounts * Polish: * Remove unused import * Fix bug with code diff viewer
1 parent d0b18bb commit 9b7a8a8

File tree

11 files changed

+60
-29
lines changed

11 files changed

+60
-29
lines changed

agents-manage-ui/src/app/[tenantId]/projects/[projectId]/agents/[agentId]/page.client.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
teamAgentNodeTargetHandleId,
2929
} from '@/components/agent/configuration/node-types';
3030
import { useCopilotContext } from '@/components/agent/copilot/copilot-context';
31+
import { CopilotStreamingOverlay } from '@/components/agent/copilot-streaming-overlay';
3132
import { EmptyState } from '@/components/agent/empty-state';
3233
import { AgentErrorSummary } from '@/components/agent/error-display/agent-error-summary';
3334
import { DefaultMarker } from '@/components/agent/markers/default-marker';
@@ -116,7 +117,11 @@ export const Agent: FC<AgentProps> = ({
116117
credentialLookup = {},
117118
}) => {
118119
const [showPlayground, setShowPlayground] = useState(false);
119-
const { isOpen: isCopilotChatOpen, isCopilotConfigured } = useCopilotContext();
120+
const {
121+
isOpen: isCopilotChatOpen,
122+
isCopilotConfigured,
123+
isStreaming: isCopilotStreaming,
124+
} = useCopilotContext();
120125

121126
const router = useRouter();
122127

@@ -1034,6 +1039,7 @@ export const Agent: FC<AgentProps> = ({
10341039
defaultSize={100}
10351040
className="relative"
10361041
>
1042+
{isCopilotStreaming && <CopilotStreamingOverlay />}
10371043
<DefaultMarker />
10381044
<SelectedMarker />
10391045
<ReactFlow
@@ -1069,6 +1075,7 @@ export const Agent: FC<AgentProps> = ({
10691075
<NodeLibrary />
10701076
</Panel>
10711077
)}
1078+
10721079
{showEmptyState && (
10731080
<Panel position="top-center" className="top-1/2! translate-y-[-50%]">
10741081
<EmptyState onAddInitialNode={onAddInitialNode} />
@@ -1132,6 +1139,7 @@ export const Agent: FC<AgentProps> = ({
11321139
subAgentExternalAgentConfigLookup={subAgentExternalAgentConfigLookup}
11331140
subAgentTeamAgentConfigLookup={subAgentTeamAgentConfigLookup}
11341141
credentialLookup={credentialLookup}
1142+
disabled={isCopilotStreaming}
11351143
/>
11361144
</ResizablePanel>
11371145
</>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Panel } from '@xyflow/react';
2+
import { Loader2 } from 'lucide-react';
3+
import { LoadingIndicator } from './copilot/message-parts/loading';
4+
5+
export const CopilotStreamingOverlay = () => {
6+
return (
7+
<>
8+
<div className="w-full h-full bg-background/50 absolute top-0 left-0 z-1" />
9+
<Panel position="top-center" className="z-10">
10+
<div className="flex items-center gap-2 bg-background dark:bg-sidebar px-4 py-2 rounded-lg shadow-[0_2px_20px_rgba(0,0,0,0.08)] dark:shadow-none z-10">
11+
<Loader2 className="w-4 h-4 animate-spin text-primary" />
12+
<LoadingIndicator
13+
messages={['Thinking', 'Reviewing agent', 'Preparing changes']}
14+
variant="tailwind"
15+
/>
16+
</div>
17+
</Panel>
18+
</>
19+
);
20+
};

agents-manage-ui/src/components/agent/copilot/components/code-diff.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import type * as Monaco from 'monaco-editor';
44
import { useTheme } from 'next-themes';
55
import type { ComponentPropsWithoutRef, FC } from 'react';
6-
import { useEffect, useRef } from 'react';
6+
import { useEffect, useId, useRef } from 'react';
77
import { MonacoEditor } from '@/components/editors/monaco-editor';
88
import { Skeleton } from '@/components/ui/skeleton';
99
import { useMonacoActions, useMonacoStore } from '@/features/agent/state/use-monaco-store';
@@ -23,13 +23,16 @@ interface CodeDiffProps extends Omit<ComponentPropsWithoutRef<'div'>, 'onChange'
2323
export const CodeDiff: FC<CodeDiffProps> = ({
2424
originalValue,
2525
newValue,
26-
originalUri = 'code-original.txt',
27-
modifiedUri = 'code-modified.txt',
26+
originalUri: originalUriProp,
27+
modifiedUri: modifiedUriProp,
2828
className,
2929
editorOptions = {},
3030
onMount,
3131
...props
3232
}) => {
33+
const instanceId = useId();
34+
const originalUri = originalUriProp ?? `code-original-${instanceId}.txt`;
35+
const modifiedUri = modifiedUriProp ?? `code-modified-${instanceId}.txt`;
3336
// If there's no original value, show a regular editor instead of a diff
3437
const hasOriginalValue = originalValue && originalValue.trim() !== '';
3538

@@ -168,7 +171,6 @@ export const CodeDiff: FC<CodeDiffProps> = ({
168171
}, [monaco, hasOriginalValue]);
169172

170173
if (!hasOriginalValue) {
171-
modifiedUri ??= `new-code.json`;
172174
return (
173175
<MonacoEditor value={newValue} uri={modifiedUri} readOnly className={className} {...props} />
174176
);

agents-manage-ui/src/components/agent/copilot/copilot-chat.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ export function CopilotChat({ agentId, tenantId, projectId, refreshAgentGraph }:
5252
},
5353
});
5454

55+
useEffect(() => {
56+
return () => setIsStreaming(false);
57+
}, [setIsStreaming]);
58+
5559
useEffect(() => {
5660
const updateAgentGraph = (event: any) => {
5761
// we need to check if the conversationId is the same as the one in the event because this event is also triggered by the 'try now' chat.

agents-manage-ui/src/components/agent/copilot/message-parts/loading.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ export const LoadingDots = () => {
2020

2121
export function LoadingIndicator({
2222
messages = ['Thinking', 'Looking for content', 'Analyzing'],
23+
variant = 'inkeep',
2324
}: {
2425
messages?: string[];
26+
variant?: 'inkeep' | 'tailwind';
2527
}) {
2628
const [messageIndex, setMessageIndex] = useState(0);
2729

@@ -38,12 +40,17 @@ export function LoadingIndicator({
3840
return () => clearInterval(interval);
3941
}, [messages.length]);
4042

43+
const shimmerClass =
44+
variant === 'inkeep'
45+
? 'bg-[linear-gradient(to_bottom_right,_var(--ikp-color-gray-700),_var(--ikp-color-gray-400))] dark:bg-[linear-gradient(to_bottom_right,_var(--ikp-color-gray-dark-300),_var(--ikp-color-gray-dark-100))]'
46+
: 'bg-[linear-gradient(to_bottom_right,_#374151,_#9ca3af)] dark:bg-[linear-gradient(to_bottom_right,_#d1d5db,_#f3f4f6)]';
47+
4148
return (
4249
<div
4350
className="flex items-center space-x-2 font-medium text-sm text-gray-700 dark:text-gray-dark-300"
4451
aria-live="polite"
4552
>
46-
<span className="animate-shimmer bg-[linear-gradient(to_bottom_right,_var(--ikp-color-gray-700),_var(--ikp-color-gray-400))] dark:bg-[linear-gradient(to_bottom_right,_var(--ikp-color-gray-dark-300),_var(--ikp-color-gray-dark-100))] bg-clip-text text-transparent">
53+
<span className={`animate-shimmer ${shimmerClass} bg-clip-text text-transparent`}>
4754
{messages[messageIndex]}
4855
</span>
4956
<div className="flex space-x-1">

agents-manage-ui/src/components/agent/ship/mcp-guide/snippets/cursor.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
export const cursorTemplate = `
22
1. Open [Cursor](https://cursor.com/docs/context/mcp). Create a \`.cursor\` directory in your project root if there isn't one already.
3-
43
2. Create or open the \`mcp.json\` file in the \`.cursor\` directory.
5-
64
3. Add the following configuration:
75
\`\`\`bash
86
{
@@ -17,11 +15,7 @@ export const cursorTemplate = `
1715
}
1816
}
1917
\`\`\`
20-
2118
4. Save the configuration file. You may need to restart Cursor to see the changes.
22-
2319
5. You can also add the configuration globally by opening the command palette (\`Cmd/Ctrl + Shift + P\`) and selecting **Cursor Settings > MCP > Add new global MCP server**.
24-
2520
6. You can verify the connection by opening the composer (\`Cmd + I\`) in **agent mode** and asking a question.
26-
2721
`;
Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
export const vscodeTemplate = `
2-
32
1. Open [Visual Studio Code](https://code.visualstudio.com/docs/copilot/customization/mcp-servers). Create a \`.vscode\` directory in your project root if there isn't one already.
4-
53
2. Create or open the \`mcp.json\` file in the \`.vscode\` directory.
6-
74
3. Add the following configuration:
8-
95
\`\`\`bash
106
{
117
"servers": {
@@ -19,9 +15,6 @@ export const vscodeTemplate = `
1915
}
2016
}
2117
\`\`\`
22-
2318
4. Save the configuration file. You may need to restart VS Code to see the changes.
24-
2519
5. You can verify the connection by opening the composer (\`Ctrl + Alt + I\`) in **agent mode** and asking a question.
26-
2720
`;
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
export const windsurfTemplate = `
2-
32
1. Open [Windsurf](https://docs.windsurf.com/windsurf/cascade/mcp). Create a \`.windsurf\` directory in your project root if there isn't one already.
4-
53
2. Create or open the \`mcp_config.json\` file in the \`.windsurf\` directory.
6-
74
3. Add the following configuration:
8-
95
\`\`\`bash
106
{
117
"mcpServers": {
@@ -18,8 +14,6 @@ export const windsurfTemplate = `
1814
}
1915
}
2016
\`\`\`
21-
2217
4. Save the configuration file. You may need to restart Windsurf to see the changes.
23-
2418
5. You can verify the connection by opening the composer (\`Cmd/Ctrl + L\`) in **code mode** and asking a question.
2519
`;

agents-manage-ui/src/components/agent/sidepane/sidepane.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ interface SidePaneProps {
4848
subAgentExternalAgentConfigLookup: SubAgentExternalAgentConfigLookup;
4949
subAgentTeamAgentConfigLookup: SubAgentTeamAgentConfigLookup;
5050
credentialLookup: Record<string, Credential>;
51+
disabled?: boolean;
5152
}
5253

5354
export function SidePane({
@@ -61,6 +62,7 @@ export function SidePane({
6162
subAgentExternalAgentConfigLookup,
6263
subAgentTeamAgentConfigLookup,
6364
credentialLookup,
65+
disabled = false,
6466
}: SidePaneProps) {
6567
const selectedNode = useNodesData(selectedNodeId || '');
6668
const edges = useEdges();
@@ -206,7 +208,11 @@ export function SidePane({
206208
</div>
207209
<SidePaneLayout.CloseButton onClick={onClose} />
208210
</SidePaneLayout.Header>
209-
<SidePaneLayout.Content>{editorContent}</SidePaneLayout.Content>
211+
<SidePaneLayout.Content>
212+
<fieldset disabled={disabled} className="contents">
213+
{editorContent}
214+
</fieldset>
215+
</SidePaneLayout.Content>
210216
</SidePaneLayout.Root>
211217
);
212218
}

agents-manage-ui/src/components/form/expandable-field.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ export function ExpandableField({
7878
<Dialog open={open} onOpenChange={onOpenChange}>
7979
<div className="space-y-2">{content}</div>
8080

81-
<DialogContent className="!max-w-none h-screen w-screen max-h-screen p-0 gap-0 border-0 rounded-none">
81+
<DialogContent
82+
size="fullscreen"
83+
className="!max-w-none h-screen w-screen max-h-screen p-0 gap-0 border-0 rounded-none"
84+
>
8285
<DialogTitle className="sr-only">{label}</DialogTitle>
8386
<DialogDescription className="sr-only">{`${label} Editor`}</DialogDescription>
8487
<div className="flex flex-col w-full px-8 pb-8 pt-12 mx-auto max-w-7xl min-w-0 gap-2">

0 commit comments

Comments
 (0)