Canvas: Implement agent sidebar on the overview tab

Change-Id: I1f2fb874cb98247c73bebf364f4669ad5170c4a0
diff --git a/apps/canvas/config/src/graph.ts b/apps/canvas/config/src/graph.ts
index 3c66fbd..c36dbcf 100644
--- a/apps/canvas/config/src/graph.ts
+++ b/apps/canvas/config/src/graph.ts
@@ -339,3 +339,4 @@
 export type ServiceInfo = z.infer<typeof serviceInfoSchema>;
 export type Env = z.infer<typeof envSchema>;
 export type Access = z.infer<typeof accessSchema>;
+export type AgentAccess = Required<Extract<Access, { type: "https" }>>;
diff --git a/apps/canvas/config/src/index.ts b/apps/canvas/config/src/index.ts
index 453416d..f8db8fe 100644
--- a/apps/canvas/config/src/index.ts
+++ b/apps/canvas/config/src/index.ts
@@ -49,6 +49,7 @@
 	envSchema,
 	accessSchema,
 	Access,
+	AgentAccess,
 } from "./graph.js";
 
 export { generateDodoConfig, configToGraph } from "./config.js";
diff --git a/apps/canvas/front/src/Overview.tsx b/apps/canvas/front/src/Overview.tsx
index 8ed2c0c..1c86aae 100644
--- a/apps/canvas/front/src/Overview.tsx
+++ b/apps/canvas/front/src/Overview.tsx
@@ -1,9 +1,11 @@
 import React, { useMemo } from "react";
-import { useStateStore, AppNode, NodeType } from "@/lib/state";
+import { useStateStore, useLeadAgent } from "@/lib/state";
 import { NodeDetails } from "./components/node-details";
 import { Actions } from "./components/actions";
 import { Canvas } from "./components/canvas";
 import { Separator } from "./components/ui/separator";
+import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "./components/ui/resizable";
+import { AppNode, NodeType } from "config";
 
 const sections: { title: string; nodes: NodeType[] }[] = [
 	{
@@ -21,6 +23,30 @@
 ];
 
 export function Overview(): React.ReactNode {
+	const leadAgent = useLeadAgent();
+	if (leadAgent) {
+		return (
+			<ResizablePanelGroup direction="horizontal" className="w-full h-full">
+				<ResizablePanel defaultSize={25}>
+					<iframe
+						key={leadAgent.name}
+						src={`${leadAgent.address}?m`}
+						title={leadAgent.agentName}
+						className="w-full h-full"
+					/>
+				</ResizablePanel>
+				<ResizableHandle withHandle />
+				<ResizablePanel defaultSize={75} className="!overflow-y-auto !overflow-x-hidden">
+					<OverviewImpl />
+				</ResizablePanel>
+			</ResizablePanelGroup>
+		);
+	} else {
+		return <OverviewImpl />;
+	}
+}
+
+function OverviewImpl(): React.ReactNode {
 	const store = useStateStore();
 	const nodes = useMemo(() => {
 		return store.nodes.filter((n) => n.type !== "network" && n.type !== "github" && n.type !== undefined);
diff --git a/apps/canvas/front/src/components/ChatManager.tsx b/apps/canvas/front/src/components/ChatManager.tsx
index d5db0f3..4731c42 100644
--- a/apps/canvas/front/src/components/ChatManager.tsx
+++ b/apps/canvas/front/src/components/ChatManager.tsx
@@ -26,7 +26,7 @@
 				return (
 					<ChatBubble
 						key={agent.name}
-						agentName={agent.name}
+						agentName={agent.agentName}
 						agentUrl={agent.address}
 						initialPosition={initialPosition}
 					/>
diff --git a/apps/canvas/front/src/lib/state.ts b/apps/canvas/front/src/lib/state.ts
index e0a858a..cd5f29c 100644
--- a/apps/canvas/front/src/lib/state.ts
+++ b/apps/canvas/front/src/lib/state.ts
@@ -14,7 +14,7 @@
 import type { DeepPartial } from "react-hook-form";
 import { v4 as uuidv4 } from "uuid";
 import { create } from "zustand";
-import { AppNode, Env, NodeType, VolumeNode, GatewayTCPData, envSchema, Access } from "config";
+import { AppNode, Env, NodeType, VolumeNode, GatewayTCPData, envSchema, AgentAccess } from "config";
 
 export function nodeLabel(n: AppNode): string {
 	try {
@@ -270,12 +270,17 @@
 	return useStateStore(envSelector);
 }
 
-export function useAgents(): Extract<Access, { type: "https" }>[] {
+export function useAgents(): AgentAccess[] {
 	return useStateStore(envSelector).access.filter(
-		(acc): acc is Extract<Access, { type: "https" }> => acc.type === "https" && acc.agentName != null,
+		(acc): acc is AgentAccess => acc.type === "https" && acc.agentName != null,
 	);
 }
 
+export function useLeadAgent(): AgentAccess | undefined {
+	const agents = useAgents();
+	return agents.find((a) => a.agentName === "dodo") || agents[0];
+}
+
 export function useGithubService(): boolean {
 	return useStateStore(envSelector).integrations.github;
 }