Update files
This commit is contained in:
@@ -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 (
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 |
Reference in New Issue
Block a user