diff --git a/src/components/SessionIcon.tsx b/src/components/SessionIcon.tsx
new file mode 100644
index 0000000..9bc2230
--- /dev/null
+++ b/src/components/SessionIcon.tsx
@@ -0,0 +1,89 @@
+import { MessageSquare, Clock, Globe, Bot } from 'lucide-react';
+import type { Session } from '../types';
+
+// SVG brand icons (not available in lucide)
+function DiscordIcon({ size = 15, className = '' }: { size?: number; className?: string }) {
+ return (
+
+ );
+}
+
+function TelegramIcon({ size = 15, className = '' }: { size?: number; className?: string }) {
+ return (
+
+ );
+}
+
+function SignalIcon({ size = 15, className = '' }: { size?: number; className?: string }) {
+ return (
+
+ );
+}
+
+function WhatsAppIcon({ size = 15, className = '' }: { size?: number; className?: string }) {
+ return (
+
+ );
+}
+
+function SlackIcon({ size = 15, className = '' }: { size?: number; className?: string }) {
+ return (
+
+ );
+}
+
+/**
+ * Returns the appropriate icon for a session based on its channel or kind.
+ * Detects cron sessions from the session key pattern.
+ */
+export function SessionIcon({ session, isActive, isCurrentSession }: {
+ session: Session;
+ isActive?: boolean;
+ isCurrentSession?: boolean;
+}) {
+ const size = 15;
+ const baseClass = isCurrentSession ? 'text-cyan-300/70' : isActive ? 'text-violet-400/70' : '';
+
+ // Detect cron sessions from key pattern
+ const isCron = session.key.includes(':cron:');
+ if (isCron) {
+ return ;
+ }
+
+ // Detect sub-agent / spawned sessions
+ const isSubAgent = session.key.includes(':spawn:') || session.key.includes(':sub:');
+ if (isSubAgent) {
+ return ;
+ }
+
+ const channel = session.channel?.toLowerCase();
+
+ switch (channel) {
+ case 'discord':
+ return ;
+ case 'telegram':
+ return ;
+ case 'signal':
+ return ;
+ case 'whatsapp':
+ return ;
+ case 'slack':
+ return ;
+ case 'webchat':
+ return ;
+ case 'teamspeak':
+ return ;
+ default:
+ return ;
+ }
+}
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx
index 8cd34a0..29b9481 100644
--- a/src/components/Sidebar.tsx
+++ b/src/components/Sidebar.tsx
@@ -1,7 +1,8 @@
import { useState, useMemo, useRef, useEffect } from 'react';
-import { MessageSquare, X, Sparkles, Search } from 'lucide-react';
+import { X, Sparkles, Search } from 'lucide-react';
import type { Session } from '../types';
import { useT } from '../hooks/useLocale';
+import { SessionIcon } from './SessionIcon';
interface Props {
sessions: Session[];
@@ -103,7 +104,7 @@ export function Sidebar({ sessions, activeSession, onSwitch, open, onClose }: Pr
}`}
>
-
+
{s.isActive && (
)}
diff --git a/src/hooks/useGateway.ts b/src/hooks/useGateway.ts
index 28ca729..ecdd3ff 100644
--- a/src/hooks/useGateway.ts
+++ b/src/hooks/useGateway.ts
@@ -90,6 +90,8 @@ export function useGateway() {
contextTokens: s.contextTokens as number | undefined,
inputTokens: s.inputTokens as number | undefined,
outputTokens: s.outputTokens as number | undefined,
+ channel: (s.lastChannel || s.channel) as string | undefined,
+ kind: s.kind as string | undefined,
})));
}
} catch {
diff --git a/src/types/index.ts b/src/types/index.ts
index dcf4400..516bc8d 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -24,6 +24,8 @@ export interface Session {
contextTokens?: number;
inputTokens?: number;
outputTokens?: number;
+ channel?: string;
+ kind?: string;
}
export type ConnectionStatus = 'disconnected' | 'connecting' | 'connected';