Merge branch 'main' of github.com:boudra/paseo into truncate-settings-title

This commit is contained in:
Mohamed Boudra
2026-02-05 18:00:21 +07:00
6 changed files with 36 additions and 13 deletions

View File

@@ -26,7 +26,7 @@ import { deriveSidebarShortcutAgentKeys } from "@/utils/sidebar-shortcuts";
import { AdaptiveModalSheet } from "@/components/adaptive-modal-sheet";
const DESKTOP_SIDEBAR_WIDTH = 320;
const SIDEBAR_AGENT_LIMIT = 15;
const SIDEBAR_AGENT_LIMIT = 50; // temporary for screenshots
interface SlidingSidebarProps {
selectedAgentId?: string;
@@ -83,12 +83,8 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
});
}, [agents]);
const limitedAgents = useMemo(
() => sortedAgents.slice(0, SIDEBAR_AGENT_LIMIT),
[sortedAgents]
);
const sidebarSections = useSidebarAgentSections(limitedAgents);
// Pass all agents to grouping, limit is applied inside groupAgents per-project
const sidebarSections = useSidebarAgentSections(sortedAgents);
const collapsedProjectKeys = useSidebarCollapsedSectionsStore((s) => s.collapsedProjectKeys);
const setSidebarShortcutAgentKeys = useKeyboardNavStore((s) => s.setSidebarShortcutAgentKeys);
const sidebarShortcutAgentKeys = useMemo(() => {
@@ -294,7 +290,7 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
{/* Middle: scrollable agent list */}
<GroupedAgentList
agents={limitedAgents}
agents={sortedAgents}
isRefreshing={isManualRefresh && isRevalidating}
onRefresh={handleRefresh}
selectedAgentId={selectedAgentId}
@@ -420,7 +416,7 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
{/* Middle: scrollable agent list */}
<GroupedAgentList
agents={limitedAgents}
agents={sortedAgents}
isRefreshing={isManualRefresh && isRevalidating}
onRefresh={handleRefresh}
selectedAgentId={selectedAgentId}

View File

@@ -89,12 +89,19 @@ export function useGlobalKeyboardNav({
const key = event.key ?? "";
const lowerKey = key.toLowerCase();
if (key === "Alt") {
if (key === "Alt" && !event.shiftKey) {
useKeyboardNavStore.getState().setAltDown(true);
}
if (isTauri && (key === "Meta" || key === "Control")) {
if (isTauri && (key === "Meta" || key === "Control") && !event.shiftKey) {
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
if (

View File

@@ -210,6 +210,9 @@ export interface GroupedAgents {
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 {
/**
* Optional function to read a remote URL for an agent.
@@ -245,10 +248,21 @@ export function groupAgents(
const isRunningOrAttention =
agent.status === "running" || agent.requiresAttention;
const isRecentlyActive =
now - agent.lastActivityAt.getTime() < ACTIVE_GRACE_PERIOD_MS;
const ageDiff = now - agent.lastActivityAt.getTime();
const isRecentlyActive = ageDiff < ACTIVE_GRACE_PERIOD_MS;
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) {
activeAgents.push(agent);
} else {

View File

@@ -1,6 +1,7 @@
import { DaemonClient } from "@server/client/daemon-client";
import type { ConnectionState } from "@server/client/daemon-client";
import { buildDaemonWebSocketUrl } from "./daemon-endpoints";
import { createTauriWebSocketTransportFactory } from "./tauri-daemon-transport";
function normalizeNonEmptyString(value: unknown): string | null {
if (typeof value !== "string") return null;
@@ -45,9 +46,11 @@ export async function probeDaemonEndpoint(
const timeoutMs = options?.timeoutMs ?? 6000;
const url = buildDaemonWebSocketUrl(endpoint);
const tauriTransportFactory = createTauriWebSocketTransportFactory();
const client = new DaemonClient({
url,
suppressSendErrors: true,
...(tauriTransportFactory ? { transportFactory: tauriTransportFactory } : {}),
});
try {

View File

@@ -136,6 +136,9 @@ export async function createPaseoDaemon(
// CORS - allow same-origin + configured origins
const allowedOrigins = new Set([
...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
...(listenTarget.type === "tcp"
? [

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB