- {hasReasoning && (
-
- )}
- {message.parts.map((part, index) => {
- const isLastPart = index === message.parts.length - 1;
- const usage = isLastPart
- ? addUsage(emptyUsageStats(), message.metadata?.usage)
- : null;
-
- return (
-
- )
- }
- dataParts={dataParts}
- isLoading={isLoading}
- isLastMessage={isLast}
- />
- );
- })}
- {isLast && isLoading && startedAt !== null && (
-
+ {isPlanMode && (
+
+
+ Plan
+
)}
+
+ {renderItems.map((item) => {
+ if (item.kind === "reasoning") {
+ // Inline reasoning block — streaming if it's the last item and we're still loading
+ const isThisStreaming = isStreaming && item === lastItem;
+ return (
+
+ );
+ }
+
+ const { part, index } = item;
+ const isLastVisible =
+ index === visibleParts.length - 1 &&
+ !isLastItemStreamingReasoning;
+ const usage = isLastVisible
+ ? addUsage(emptyUsageStats(), message.metadata?.usage)
+ : null;
+
+ return (
+
+ )
+ }
+ dataParts={dataParts}
+ isLoading={isLoading}
+ isLastMessage={isLast}
+ />
+ );
+ })}
+ {isLast && !isLoading && dataParts.promptSuggestions.length > 0 && (
+
+ )}
+ {isLast && isLoading && startedAt !== null && (
+
+ )}
+
+ {isLast && !isLoading && isPlanMode &&
}
) : isLoading ? (
{/* Sticky overlay to prevent scrolling content from appearing above the user message */}
@@ -88,6 +90,7 @@ export function MessagePair({ pair, isLastPair, status }: MessagePairProps) {
message={pair.assistant}
status={status}
isLast={isLastPair}
+ isPlanMode={isPlanMode}
/>
);
diff --git a/apps/mesh/src/web/components/chat/message/parts/tool-call-part/connection-auth.tsx b/apps/mesh/src/web/components/chat/message/parts/tool-call-part/connection-auth.tsx
new file mode 100644
index 0000000000..1bb519b588
--- /dev/null
+++ b/apps/mesh/src/web/components/chat/message/parts/tool-call-part/connection-auth.tsx
@@ -0,0 +1,313 @@
+"use client";
+
+import { Button } from "@deco/ui/components/button.tsx";
+import { Input } from "@deco/ui/components/input.tsx";
+import { cn } from "@deco/ui/lib/utils.ts";
+import { authenticateMcp } from "@decocms/mesh-sdk";
+import { Check, Loading01, Lock01 } from "@untitledui/icons";
+import type { ToolUIPart } from "ai";
+import { useState } from "react";
+import { ToolCallShell } from "./common.tsx";
+import { getEffectiveState } from "./utils.tsx";
+
+interface AuthData {
+ connection_id: string;
+ title: string;
+ icon: string | null;
+ description: string | null;
+ connection_url: string | null;
+ status: string;
+ needs_auth: boolean;
+ auth_type: string;
+}
+
+function parseAuthData(output: unknown): AuthData | null {
+ if (!output || typeof output !== "object") return null;
+ const data = output as Record