Update files

This commit is contained in:
Mohamed Boudra
2026-02-05 18:00:09 +07:00
parent 9f479dd337
commit cb3cf1c209
7 changed files with 41 additions and 15 deletions
+5 -2
View File
@@ -114,17 +114,20 @@ const styles = StyleSheet.create((theme) => ({
hostHeaderRow: { hostHeaderRow: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
justifyContent: "space-between", gap: theme.spacing[3],
}, },
hostHeaderRight: { hostHeaderRight: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
gap: theme.spacing[2], gap: theme.spacing[2],
flexShrink: 0,
}, },
hostLabel: { hostLabel: {
color: theme.colors.foreground, color: theme.colors.foreground,
fontSize: theme.fontSize.base, fontSize: theme.fontSize.base,
fontWeight: theme.fontWeight.normal, fontWeight: theme.fontWeight.normal,
flex: 1,
flexShrink: 1,
}, },
hostError: { hostError: {
color: theme.colors.palette.red[300], color: theme.colors.palette.red[300],
@@ -1055,7 +1058,7 @@ function DaemonCard({
<View style={styles.hostCard} testID={`daemon-card-${daemon.serverId}`}> <View style={styles.hostCard} testID={`daemon-card-${daemon.serverId}`}>
<View style={styles.hostCardContent}> <View style={styles.hostCardContent}>
<View style={styles.hostHeaderRow}> <View style={styles.hostHeaderRow}>
<Text style={styles.hostLabel}>{daemon.label}</Text> <Text style={styles.hostLabel} numberOfLines={1}>{daemon.label}</Text>
<View style={styles.hostHeaderRight}> <View style={styles.hostHeaderRight}>
<View style={[styles.statusPill, { backgroundColor: statusPillBg }]}> <View style={[styles.statusPill, { backgroundColor: statusPillBg }]}>
<View style={[styles.statusDot, { backgroundColor: statusColor }]} /> <View style={[styles.statusDot, { backgroundColor: statusColor }]} />
@@ -26,7 +26,7 @@ import { deriveSidebarShortcutAgentKeys } from "@/utils/sidebar-shortcuts";
import { AdaptiveModalSheet } from "@/components/adaptive-modal-sheet"; import { AdaptiveModalSheet } from "@/components/adaptive-modal-sheet";
const DESKTOP_SIDEBAR_WIDTH = 320; const DESKTOP_SIDEBAR_WIDTH = 320;
const SIDEBAR_AGENT_LIMIT = 15; const SIDEBAR_AGENT_LIMIT = 50; // temporary for screenshots
interface SlidingSidebarProps { interface SlidingSidebarProps {
selectedAgentId?: string; selectedAgentId?: string;
@@ -83,12 +83,8 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
}); });
}, [agents]); }, [agents]);
const limitedAgents = useMemo( // Pass all agents to grouping, limit is applied inside groupAgents per-project
() => sortedAgents.slice(0, SIDEBAR_AGENT_LIMIT), const sidebarSections = useSidebarAgentSections(sortedAgents);
[sortedAgents]
);
const sidebarSections = useSidebarAgentSections(limitedAgents);
const collapsedProjectKeys = useSidebarCollapsedSectionsStore((s) => s.collapsedProjectKeys); const collapsedProjectKeys = useSidebarCollapsedSectionsStore((s) => s.collapsedProjectKeys);
const setSidebarShortcutAgentKeys = useKeyboardNavStore((s) => s.setSidebarShortcutAgentKeys); const setSidebarShortcutAgentKeys = useKeyboardNavStore((s) => s.setSidebarShortcutAgentKeys);
const sidebarShortcutAgentKeys = useMemo(() => { const sidebarShortcutAgentKeys = useMemo(() => {
@@ -294,7 +290,7 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
{/* Middle: scrollable agent list */} {/* Middle: scrollable agent list */}
<GroupedAgentList <GroupedAgentList
agents={limitedAgents} agents={sortedAgents}
isRefreshing={isManualRefresh && isRevalidating} isRefreshing={isManualRefresh && isRevalidating}
onRefresh={handleRefresh} onRefresh={handleRefresh}
selectedAgentId={selectedAgentId} selectedAgentId={selectedAgentId}
@@ -420,7 +416,7 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
{/* Middle: scrollable agent list */} {/* Middle: scrollable agent list */}
<GroupedAgentList <GroupedAgentList
agents={limitedAgents} agents={sortedAgents}
isRefreshing={isManualRefresh && isRevalidating} isRefreshing={isManualRefresh && isRevalidating}
onRefresh={handleRefresh} onRefresh={handleRefresh}
selectedAgentId={selectedAgentId} selectedAgentId={selectedAgentId}
@@ -89,12 +89,19 @@ export function useGlobalKeyboardNav({
const key = event.key ?? ""; const key = event.key ?? "";
const lowerKey = key.toLowerCase(); const lowerKey = key.toLowerCase();
if (key === "Alt") { if (key === "Alt" && !event.shiftKey) {
useKeyboardNavStore.getState().setAltDown(true); useKeyboardNavStore.getState().setAltDown(true);
} }
if (isTauri && (key === "Meta" || key === "Control")) { if (isTauri && (key === "Meta" || key === "Control") && !event.shiftKey) {
useKeyboardNavStore.getState().setCmdOrCtrlDown(true); useKeyboardNavStore.getState().setCmdOrCtrlDown(true);
} }
// If shift is pressed while a modifier is held, hide the badges
if (key === "Shift") {
const state = useKeyboardNavStore.getState();
if (state.altDown || state.cmdOrCtrlDown) {
state.resetModifiers();
}
}
// Cmd+B: toggle sidebar // Cmd+B: toggle sidebar
if ( if (
+16 -2
View File
@@ -210,6 +210,9 @@ export interface GroupedAgents {
const ACTIVE_GRACE_PERIOD_MS = 2 * 24 * 60 * 60 * 1000; // 2 days (temporary for screenshots) const ACTIVE_GRACE_PERIOD_MS = 2 * 24 * 60 * 60 * 1000; // 2 days (temporary for screenshots)
// eslint-disable-next-line no-console
console.log('[agent-grouping] ACTIVE_GRACE_PERIOD_MS:', ACTIVE_GRACE_PERIOD_MS, 'ms =', ACTIVE_GRACE_PERIOD_MS / (1000 * 60 * 60), 'hours');
interface GroupAgentsOptions { interface GroupAgentsOptions {
/** /**
* Optional function to read a remote URL for an agent. * Optional function to read a remote URL for an agent.
@@ -245,10 +248,21 @@ export function groupAgents(
const isRunningOrAttention = const isRunningOrAttention =
agent.status === "running" || agent.requiresAttention; agent.status === "running" || agent.requiresAttention;
const isRecentlyActive = const ageDiff = now - agent.lastActivityAt.getTime();
now - agent.lastActivityAt.getTime() < ACTIVE_GRACE_PERIOD_MS; const isRecentlyActive = ageDiff < ACTIVE_GRACE_PERIOD_MS;
const isActive = isRunningOrAttention || isRecentlyActive; const isActive = isRunningOrAttention || isRecentlyActive;
// eslint-disable-next-line no-console
console.log('[agent-grouping] agent:', agent.title || agent.id, {
status: agent.status,
lastActivityAt: agent.lastActivityAt,
ageDiffHours: ageDiff / (1000 * 60 * 60),
gracePeriodHours: ACTIVE_GRACE_PERIOD_MS / (1000 * 60 * 60),
isRunningOrAttention,
isRecentlyActive,
isActive,
});
if (isActive) { if (isActive) {
activeAgents.push(agent); activeAgents.push(agent);
} else { } else {
@@ -1,6 +1,7 @@
import { DaemonClient } from "@server/client/daemon-client"; import { DaemonClient } from "@server/client/daemon-client";
import type { ConnectionState } from "@server/client/daemon-client"; import type { ConnectionState } from "@server/client/daemon-client";
import { buildDaemonWebSocketUrl } from "./daemon-endpoints"; import { buildDaemonWebSocketUrl } from "./daemon-endpoints";
import { createTauriWebSocketTransportFactory } from "./tauri-daemon-transport";
function normalizeNonEmptyString(value: unknown): string | null { function normalizeNonEmptyString(value: unknown): string | null {
if (typeof value !== "string") return null; if (typeof value !== "string") return null;
@@ -45,9 +46,11 @@ export async function probeDaemonEndpoint(
const timeoutMs = options?.timeoutMs ?? 6000; const timeoutMs = options?.timeoutMs ?? 6000;
const url = buildDaemonWebSocketUrl(endpoint); const url = buildDaemonWebSocketUrl(endpoint);
const tauriTransportFactory = createTauriWebSocketTransportFactory();
const client = new DaemonClient({ const client = new DaemonClient({
url, url,
suppressSendErrors: true, suppressSendErrors: true,
...(tauriTransportFactory ? { transportFactory: tauriTransportFactory } : {}),
}); });
try { try {
+3
View File
@@ -136,6 +136,9 @@ export async function createPaseoDaemon(
// CORS - allow same-origin + configured origins // CORS - allow same-origin + configured origins
const allowedOrigins = new Set([ const allowedOrigins = new Set([
...config.corsAllowedOrigins, ...config.corsAllowedOrigins,
// Tauri desktop app WebView origin (used for fetch/WebSocket in production builds).
// This origin can't be produced by normal websites, so it's safe to allow by default.
"tauri://localhost",
// For TCP, add localhost variants // For TCP, add localhost variants
...(listenTarget.type === "tcp" ...(listenTarget.type === "tcp"
? [ ? [
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB