Remove active host dependency from UI actions

This commit is contained in:
Mohamed Boudra
2025-11-26 18:04:40 +01:00
parent e6d2998904
commit 5807f62f1a
8 changed files with 57 additions and 129 deletions
@@ -82,21 +82,9 @@ export default function AgentScreen() {
const { serverId, agentId } = useLocalSearchParams<{ serverId: string; agentId: string }>(); const { serverId, agentId } = useLocalSearchParams<{ serverId: string; agentId: string }>();
const resolvedAgentId = typeof agentId === "string" ? agentId : undefined; const resolvedAgentId = typeof agentId === "string" ? agentId : undefined;
const resolvedServerId = typeof serverId === "string" ? serverId : undefined; const resolvedServerId = typeof serverId === "string" ? serverId : undefined;
const { connectionStates, activeDaemonId, setActiveDaemonId } = useDaemonConnections(); const { connectionStates } = useDaemonConnections();
const hasConnectionEntry = resolvedServerId ? connectionStates.has(resolvedServerId) : false; const hasConnectionEntry = resolvedServerId ? connectionStates.has(resolvedServerId) : false;
useEffect(() => {
if (!resolvedServerId || !hasConnectionEntry) {
return;
}
if (activeDaemonId === resolvedServerId) {
return;
}
setActiveDaemonId(resolvedServerId, { source: "agent_route" });
}, [resolvedServerId, hasConnectionEntry, activeDaemonId, setActiveDaemonId]);
const session = useDaemonSession(resolvedServerId, { const session = useDaemonSession(resolvedServerId, {
suppressUnavailableAlert: true, suppressUnavailableAlert: true,
allowUnavailable: true, allowUnavailable: true,
@@ -644,7 +632,7 @@ function AgentSessionUnavailableState({
Cannot open this agent because {serverLabel} is not configured on this device. Cannot open this agent because {serverLabel} is not configured on this device.
</Text> </Text>
<Text style={styles.statusText}> <Text style={styles.statusText}>
Add the daemon in Settings or open an agent on a configured server to continue. Add the host in Settings or open an agent on a configured server to continue.
</Text> </Text>
</View> </View>
</View> </View>
@@ -661,7 +649,7 @@ function AgentSessionUnavailableState({
<> <>
<ActivityIndicator size="large" /> <ActivityIndicator size="large" />
<Text style={styles.loadingText}>Connecting to {serverLabel}...</Text> <Text style={styles.loadingText}>Connecting to {serverLabel}...</Text>
<Text style={styles.statusText}>We will show this agent once the daemon is online.</Text> <Text style={styles.statusText}>We will show this agent once the host is online.</Text>
</> </>
) : ( ) : (
<> <>
@@ -669,7 +657,7 @@ function AgentSessionUnavailableState({
Cannot open this agent while {serverLabel} is {connectionStatusLabel.toLowerCase()}. Cannot open this agent while {serverLabel} is {connectionStatusLabel.toLowerCase()}.
</Text> </Text>
<Text style={styles.statusText}> <Text style={styles.statusText}>
Connect this daemon or switch to another one to continue. Connect this host or switch to another one to continue.
</Text> </Text>
{lastError ? <Text style={styles.errorDetails}>{lastError}</Text> : null} {lastError ? <Text style={styles.errorDetails}>{lastError}</Text> : null}
</> </>
+7 -12
View File
@@ -18,7 +18,7 @@ export default function HomeScreen() {
const { theme } = useUnistyles(); const { theme } = useUnistyles();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const { agents } = useSession(); const { agents } = useSession();
const { activeDaemonId, connectionStates } = useDaemonConnections(); const { connectionStates } = useDaemonConnections();
const aggregatedAgents = useAggregatedAgents(agents); const aggregatedAgents = useAggregatedAgents(agents);
const [showCreateModal, setShowCreateModal] = useState(false); const [showCreateModal, setShowCreateModal] = useState(false);
const [showImportModal, setShowImportModal] = useState(false); const [showImportModal, setShowImportModal] = useState(false);
@@ -63,15 +63,11 @@ export default function HomeScreen() {
setShowCreateModal(true); setShowCreateModal(true);
}, []); }, []);
const openImportModal = useCallback( const openImportModal = useCallback((serverIdOverride?: string | null) => {
(serverIdOverride?: string | null) => { setPendingImportServerId(serverIdOverride ?? null);
const resolvedServerId = serverIdOverride ?? activeDaemonId ?? null; setImportModalMounted(true);
setPendingImportServerId(resolvedServerId); setShowImportModal(true);
setImportModalMounted(true); }, []);
setShowImportModal(true);
},
[activeDaemonId]
);
const handleImportAgent = useCallback(() => { const handleImportAgent = useCallback(() => {
openImportModal(); openImportModal();
@@ -166,14 +162,13 @@ export default function HomeScreen() {
<CreateAgentModal <CreateAgentModal
isVisible={showCreateModal} isVisible={showCreateModal}
onClose={handleCloseCreateModal} onClose={handleCloseCreateModal}
serverId={activeDaemonId}
/> />
) : null} ) : null}
{importModalMounted ? ( {importModalMounted ? (
<ImportAgentModal <ImportAgentModal
isVisible={showImportModal} isVisible={showImportModal}
onClose={handleCloseImportModal} onClose={handleCloseImportModal}
serverId={pendingImportServerId ?? activeDaemonId} serverId={pendingImportServerId}
/> />
) : null} ) : null}
</View> </View>
+15 -15
View File
@@ -6,7 +6,6 @@ import type { Agent } from "@/contexts/session-context";
import { formatTimeAgo } from "@/utils/time"; import { formatTimeAgo } from "@/utils/time";
import { getAgentStatusColor, getAgentStatusLabel } from "@/utils/agent-status"; import { getAgentStatusColor, getAgentStatusLabel } from "@/utils/agent-status";
import { getAgentProviderDefinition } from "@server/server/agent/provider-manifest"; import { getAgentProviderDefinition } from "@server/server/agent/provider-manifest";
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
import { type AggregatedAgentGroup } from "@/hooks/use-aggregated-agents"; import { type AggregatedAgentGroup } from "@/hooks/use-aggregated-agents";
import { useDaemonSession } from "@/hooks/use-daemon-session"; import { useDaemonSession } from "@/hooks/use-daemon-session";
@@ -16,7 +15,6 @@ interface AgentListProps {
export function AgentList({ agentGroups }: AgentListProps) { export function AgentList({ agentGroups }: AgentListProps) {
const { theme } = useUnistyles(); const { theme } = useUnistyles();
const { setActiveDaemonId } = useDaemonConnections();
const [actionAgent, setActionAgent] = useState<Agent | null>(null); const [actionAgent, setActionAgent] = useState<Agent | null>(null);
const [actionAgentServerId, setActionAgentServerId] = useState<string | null>(null); const [actionAgentServerId, setActionAgentServerId] = useState<string | null>(null);
const actionSession = useDaemonSession(actionAgentServerId ?? undefined, { const actionSession = useDaemonSession(actionAgentServerId ?? undefined, {
@@ -28,19 +26,21 @@ export function AgentList({ agentGroups }: AgentListProps) {
const isActionSheetVisible = actionAgent !== null; const isActionSheetVisible = actionAgent !== null;
const isActionDaemonUnavailable = Boolean(actionAgentServerId && !actionSession); const isActionDaemonUnavailable = Boolean(actionAgentServerId && !actionSession);
const handleAgentPress = useCallback((serverId: string, agentId: string) => { const handleAgentPress = useCallback(
if (isActionSheetVisible) { (serverId: string, agentId: string) => {
return; if (isActionSheetVisible) {
} return;
setActiveDaemonId(serverId, { source: "agent_row_press" }); }
router.push({ router.push({
pathname: "/agent/[serverId]/[agentId]", pathname: "/agent/[serverId]/[agentId]",
params: { params: {
serverId, serverId,
agentId, agentId,
}, },
}); });
}, [isActionSheetVisible, setActiveDaemonId]); },
[isActionSheetVisible]
);
const handleAgentLongPress = useCallback((serverId: string, agent: Agent) => { const handleAgentLongPress = useCallback((serverId: string, agent: Agent) => {
setActionAgentServerId(serverId); setActionAgentServerId(serverId);
@@ -215,17 +215,14 @@ function AgentFlowModal({
const isCreateFlow = !isImportFlow; const isCreateFlow = !isImportFlow;
const { recentPaths, addRecentPath } = useRecentPaths(); const { recentPaths, addRecentPath } = useRecentPaths();
const { connectionStates, activeDaemonId, setActiveDaemonId } = useDaemonConnections(); const { connectionStates } = useDaemonConnections();
const daemonEntries = useMemo(() => Array.from(connectionStates.values()), [connectionStates]); const daemonEntries = useMemo(() => Array.from(connectionStates.values()), [connectionStates]);
const initialServerId = useMemo(() => { const initialServerId = useMemo(() => {
if (serverId) { if (serverId) {
return serverId; return serverId;
} }
if (activeDaemonId) {
return activeDaemonId;
}
return daemonEntries[0]?.daemon.id ?? null; return daemonEntries[0]?.daemon.id ?? null;
}, [serverId, activeDaemonId, daemonEntries]); }, [serverId, daemonEntries]);
const [selectedServerId, setSelectedServerId] = useState<string | null>(initialServerId); const [selectedServerId, setSelectedServerId] = useState<string | null>(initialServerId);
const activeSession = useSession(); const activeSession = useSession();
const selectedSession = useSessionForServer(selectedServerId); const selectedSession = useSessionForServer(selectedServerId);
@@ -308,8 +305,8 @@ function AgentFlowModal({
} = gitRepoInfoRequest; } = gitRepoInfoRequest;
const isWsConnected = ws?.isConnected ?? false; const isWsConnected = ws?.isConnected ?? false;
const router = useRouter(); const router = useRouter();
const activeServerId = session?.serverId ?? null; const sessionServerId = session?.serverId ?? null;
const selectedDaemonId = selectedServerId ?? activeServerId; const selectedDaemonId = selectedServerId ?? sessionServerId;
const selectedDaemonConnection = selectedDaemonId const selectedDaemonConnection = selectedDaemonId
? connectionStates.get(selectedDaemonId) ? connectionStates.get(selectedDaemonId)
: null; : null;
@@ -330,8 +327,6 @@ function AgentFlowModal({
const selectedDaemonStatusLabel = formatConnectionStatus(selectedDaemonStatus); const selectedDaemonStatusLabel = formatConnectionStatus(selectedDaemonStatus);
const selectedDaemonIsUnavailable = const selectedDaemonIsUnavailable =
!session || selectedDaemonStatus !== "online" || !ws?.isConnected; !session || selectedDaemonStatus !== "online" || !ws?.isConnected;
const isBackgroundDaemonTarget =
Boolean(selectedDaemonId && activeDaemonId && selectedDaemonId !== activeDaemonId);
const selectedDaemonLastError = selectedDaemonConnection?.lastError?.trim(); const selectedDaemonLastError = selectedDaemonConnection?.lastError?.trim();
const daemonAvailabilityError = selectedDaemonIsUnavailable const daemonAvailabilityError = selectedDaemonIsUnavailable
? `${selectedDaemonLabel} is ${selectedDaemonStatusLabel}. Connect to it before creating or importing agents.${ ? `${selectedDaemonLabel} is ${selectedDaemonStatusLabel}. Connect to it before creating or importing agents.${
@@ -407,6 +402,7 @@ function AgentFlowModal({
typeof InteractionManager.runAfterInteractions typeof InteractionManager.runAfterInteractions
> | null>(null); > | null>(null);
const pendingNavigationAgentIdRef = useRef<string | null>(null); const pendingNavigationAgentIdRef = useRef<string | null>(null);
const pendingNavigationServerIdRef = useRef<string | null>(null);
const openDropdownSheet = useCallback((key: DropdownKey) => { const openDropdownSheet = useCallback((key: DropdownKey) => {
setOpenDropdown(key); setOpenDropdown(key);
}, []); }, []);
@@ -862,45 +858,17 @@ function AgentFlowModal({
type: "offline_daemon_action_attempt", type: "offline_daemon_action_attempt",
action, action,
daemonId: selectedDaemonId, daemonId: selectedDaemonId,
activeDaemonId,
status: selectedDaemonStatus ?? null, status: selectedDaemonStatus ?? null,
isBackground: isBackgroundDaemonTarget,
reason: reason ?? daemonAvailabilityError, reason: reason ?? daemonAvailabilityError,
}); });
}, },
[ [
activeDaemonId,
daemonAvailabilityError, daemonAvailabilityError,
isBackgroundDaemonTarget,
selectedDaemonId, selectedDaemonId,
selectedDaemonStatus, selectedDaemonStatus,
] ]
); );
const logBackgroundAgentAction = useCallback(
(
action: "create" | "resume",
payload: { cwd?: string; provider?: string; modeId?: string; model?: string; baseBranch?: string }
) => {
if (!isBackgroundDaemonTarget || !selectedDaemonId) {
return;
}
trackAnalyticsEvent({
type: "background_agent_action",
action,
daemonId: selectedDaemonId,
activeDaemonId,
isBackground: true,
cwd: payload.cwd,
provider: payload.provider,
modeId: payload.modeId,
model: payload.model,
baseBranch: payload.baseBranch,
});
},
[activeDaemonId, isBackgroundDaemonTarget, selectedDaemonId]
);
const resetFormState = useCallback(() => { const resetFormState = useCallback(() => {
setInitialPrompt(""); setInitialPrompt("");
promptBaselineHeightRef.current = null; promptBaselineHeightRef.current = null;
@@ -918,6 +886,7 @@ function AgentFlowModal({
resetRepoInfo(); resetRepoInfo();
setOpenDropdown(null); setOpenDropdown(null);
pendingRequestIdRef.current = null; pendingRequestIdRef.current = null;
pendingNavigationServerIdRef.current = null;
shouldSyncBaseBranchRef.current = true; shouldSyncBaseBranchRef.current = true;
dictationRequestIdRef.current = null; dictationRequestIdRef.current = null;
setIsDictating(false); setIsDictating(false);
@@ -1024,24 +993,23 @@ function AgentFlowModal({
const navigateToAgentIfNeeded = useCallback(() => { const navigateToAgentIfNeeded = useCallback(() => {
const agentId = pendingNavigationAgentIdRef.current; const agentId = pendingNavigationAgentIdRef.current;
if (!agentId || !activeServerId) { const targetServerId = pendingNavigationServerIdRef.current ?? selectedDaemonId;
if (!agentId || !targetServerId) {
return; return;
} }
pendingNavigationAgentIdRef.current = null; pendingNavigationAgentIdRef.current = null;
if (activeDaemonId !== activeServerId) { pendingNavigationServerIdRef.current = null;
setActiveDaemonId(activeServerId, { source: "agent_create_resume_nav" });
}
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {
router.push({ router.push({
pathname: "/agent/[serverId]/[agentId]", pathname: "/agent/[serverId]/[agentId]",
params: { params: {
serverId: activeServerId, serverId: targetServerId,
agentId, agentId,
}, },
}); });
}); });
}, [activeDaemonId, activeServerId, router, setActiveDaemonId]); }, [router, selectedDaemonId]);
const handleSelectServer = useCallback((serverId: string) => { const handleSelectServer = useCallback((serverId: string) => {
setSelectedServerId(serverId); setSelectedServerId(serverId);
@@ -1408,6 +1376,7 @@ function AgentFlowModal({
const requestId = generateMessageId(); const requestId = generateMessageId();
pendingRequestIdRef.current = requestId; pendingRequestIdRef.current = requestId;
pendingNavigationServerIdRef.current = selectedDaemonId ?? null;
setIsLoading(true); setIsLoading(true);
setErrorMessage(""); setErrorMessage("");
@@ -1443,14 +1412,6 @@ function AgentFlowModal({
} }
: undefined; : undefined;
logBackgroundAgentAction("create", {
cwd: trimmedPath,
provider: selectedProvider,
modeId,
model: trimmedModel,
baseBranch: trimmedBaseBranch || undefined,
});
try { try {
createAgent({ createAgent({
config, config,
@@ -1463,6 +1424,7 @@ function AgentFlowModal({
setErrorMessage("Failed to create agent. Please try again."); setErrorMessage("Failed to create agent. Please try again.");
setIsLoading(false); setIsLoading(false);
pendingRequestIdRef.current = null; pendingRequestIdRef.current = null;
pendingNavigationServerIdRef.current = null;
} }
}, [ }, [
workingDir, workingDir,
@@ -1475,7 +1437,6 @@ function AgentFlowModal({
repoInfo, repoInfo,
selectedMode, selectedMode,
modeOptions, modeOptions,
logBackgroundAgentAction,
logOfflineDaemonAction, logOfflineDaemonAction,
selectedProvider, selectedProvider,
isLoading, isLoading,
@@ -1484,6 +1445,7 @@ function AgentFlowModal({
createAgent, createAgent,
daemonAvailabilityError, daemonAvailabilityError,
isTargetDaemonReady, isTargetDaemonReady,
selectedDaemonId,
]); ]);
const handleImportCandidatePress = useCallback( const handleImportCandidatePress = useCallback(
@@ -1499,13 +1461,10 @@ function AgentFlowModal({
); );
return; return;
} }
logBackgroundAgentAction("resume", {
cwd: candidate.cwd,
provider: candidate.provider,
});
setErrorMessage(""); setErrorMessage("");
const requestId = generateMessageId(); const requestId = generateMessageId();
pendingRequestIdRef.current = requestId; pendingRequestIdRef.current = requestId;
pendingNavigationServerIdRef.current = selectedDaemonId ?? null;
setIsLoading(true); setIsLoading(true);
resumeAgent({ resumeAgent({
handle: candidate.persistence, handle: candidate.persistence,
@@ -1515,10 +1474,10 @@ function AgentFlowModal({
[ [
daemonAvailabilityError, daemonAvailabilityError,
isLoading, isLoading,
logBackgroundAgentAction,
logOfflineDaemonAction, logOfflineDaemonAction,
isTargetDaemonReady, isTargetDaemonReady,
resumeAgent, resumeAgent,
selectedDaemonId,
setImportError, setImportError,
] ]
); );
@@ -1603,6 +1562,7 @@ function AgentFlowModal({
return; return;
} }
pendingRequestIdRef.current = null; pendingRequestIdRef.current = null;
pendingNavigationServerIdRef.current = null;
setIsLoading(false); setIsLoading(false);
setErrorMessage( setErrorMessage(
payload.error ?? payload.error ??
@@ -7,7 +7,6 @@ import { AudioLines, Users, Plus, Download } from "lucide-react-native";
import { useRealtime } from "@/contexts/realtime-context"; import { useRealtime } from "@/contexts/realtime-context";
import { useSession } from "@/contexts/session-context"; import { useSession } from "@/contexts/session-context";
import { useFooterControls, FOOTER_HEIGHT } from "@/contexts/footer-controls-context"; import { useFooterControls, FOOTER_HEIGHT } from "@/contexts/footer-controls-context";
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
import { RealtimeControls } from "./realtime-controls"; import { RealtimeControls } from "./realtime-controls";
import { CreateAgentModal, ImportAgentModal } from "./create-agent-modal"; import { CreateAgentModal, ImportAgentModal } from "./create-agent-modal";
import Animated, { import Animated, {
@@ -24,7 +23,6 @@ export function GlobalFooter() {
const router = useRouter(); const router = useRouter();
const { isRealtimeMode, startRealtime } = useRealtime(); const { isRealtimeMode, startRealtime } = useRealtime();
const { ws } = useSession(); const { ws } = useSession();
const { activeDaemonId } = useDaemonConnections();
const { controls } = useFooterControls(); const { controls } = useFooterControls();
const [showCreateModal, setShowCreateModal] = useState(false); const [showCreateModal, setShowCreateModal] = useState(false);
const [showImportModal, setShowImportModal] = useState(false); const [showImportModal, setShowImportModal] = useState(false);
@@ -188,12 +186,10 @@ export function GlobalFooter() {
<CreateAgentModal <CreateAgentModal
isVisible={showCreateModal} isVisible={showCreateModal}
onClose={() => setShowCreateModal(false)} onClose={() => setShowCreateModal(false)}
serverId={activeDaemonId}
/> />
<ImportAgentModal <ImportAgentModal
isVisible={showImportModal} isVisible={showImportModal}
onClose={() => setShowImportModal(false)} onClose={() => setShowImportModal(false)}
serverId={activeDaemonId}
/> />
</> </>
); );
@@ -26,9 +26,8 @@ const sortAgents = (agents: Agent[]): Agent[] => {
}; };
export function useAggregatedAgents(fallbackAgents: Map<string, Agent>): AggregatedAgentGroup[] { export function useAggregatedAgents(fallbackAgents: Map<string, Agent>): AggregatedAgentGroup[] {
const { activeDaemonId, connectionStates } = useDaemonConnections(); const { connectionStates } = useDaemonConnections();
const sessionDirectory = useSessionDirectory(); const sessionDirectory = useSessionDirectory();
const activeServerId = activeDaemonId ?? "default";
return useMemo(() => { return useMemo(() => {
const groups = new Map<string, { serverLabel: string; agents: Agent[] }>(); const groups = new Map<string, { serverLabel: string; agents: Agent[] }>();
@@ -57,10 +56,11 @@ export function useAggregatedAgents(fallbackAgents: Map<string, Agent>): Aggrega
} }
if (groups.size === 0) { if (groups.size === 0) {
const label = connectionStates.get(activeServerId)?.daemon.label ?? activeServerId; const fallbackServerId = connectionStates.keys().next().value ?? "default";
const label = connectionStates.get(fallbackServerId)?.daemon.label ?? fallbackServerId;
const fallbackList = Array.from(fallbackAgents.values()); const fallbackList = Array.from(fallbackAgents.values());
if (fallbackList.length > 0) { if (fallbackList.length > 0) {
groups.set(activeServerId, { serverLabel: label, agents: fallbackList }); groups.set(fallbackServerId, { serverLabel: label, agents: fallbackList });
} }
} }
@@ -86,5 +86,5 @@ export function useAggregatedAgents(fallbackAgents: Map<string, Agent>): Aggrega
}); });
return aggregatedGroups; return aggregatedGroups;
}, [sessionDirectory, fallbackAgents, activeServerId, connectionStates]); }, [sessionDirectory, fallbackAgents, connectionStates]);
} }
-15
View File
@@ -1,4 +1,3 @@
type BackgroundAgentAction = "create" | "resume";
type OfflineAction = type OfflineAction =
| "create" | "create"
| "resume" | "resume"
@@ -12,25 +11,11 @@ type AnalyticsEvent =
previousDaemonId: string | null; previousDaemonId: string | null;
source?: string; source?: string;
} }
| {
type: "background_agent_action";
action: BackgroundAgentAction;
daemonId: string;
activeDaemonId: string | null;
isBackground: boolean;
cwd?: string;
provider?: string;
modeId?: string;
model?: string;
baseBranch?: string;
}
| { | {
type: "offline_daemon_action_attempt"; type: "offline_daemon_action_attempt";
action: OfflineAction; action: OfflineAction;
daemonId: string | null; daemonId: string | null;
activeDaemonId: string | null;
status: string | null; status: string | null;
isBackground: boolean;
reason?: string | null; reason?: string | null;
}; };
+9 -5
View File
@@ -22,12 +22,16 @@ The multi-daemon infrastructure is in place: session directory with daemon-scope
### 2. Remove Active/Primary/Auto-Connect Concepts ### 2. Remove Active/Primary/Auto-Connect Concepts
- [x] Remove the concept of "active daemon" from the UI and simplify to just "hosts". - [x] Remove the concept of "active daemon" from the UI and simplify to just "hosts".
- Removed the Settings "Set Active" controls/labels, scrubbed the copy that mentioned an active host (including git diff fallback text), and left the per-host cards focused on status/default/test actions; no automated tests were run. - Summary: Home/footer actions, create/import flows, and agent navigation now route directly via explicit host IDs with analytics/docs/aggregated list updates, verified with `npm run typecheck --workspace=@paseo/app`.
- [x] Remove the concept of "primary daemon"—no default host for actions. - Context: `GlobalFooter`, the create/import modals, the agent screen, and the agent list previously read/write `activeDaemonId`, forcing a global active host before routing; they now rely on explicit host IDs instead.
- Removed the Default host toggle/state in the registry and settings UI, updated host docs, and kept connection fallback logic simple; tests not run (not requested). - [ ] Remove the concept of "primary daemon"—no default host for actions.
- Context: `DaemonConnectionsProvider` still persists `activeDaemonId` in AsyncStorage and `MultiDaemonSessionHost` filters by `primary` roles to decide which hosts stay backgrounded, so the “primary/default” pipeline is intact and needs to be unwound.
- [ ] Remove the "auto-connect" toggle from host settings—hosts always auto-connect when added. - [ ] Remove the "auto-connect" toggle from host settings—hosts always auto-connect when added.
- [ ] Clean up any related state/UI that exposes these concepts to users. - [ ] Clean up any related state/UI that exposes these concepts to users.
### Review: No Silent Defaults
- [ ] Review the changes to ensure we didn't just replace "active daemon" with "first host" (e.g., `hosts[0]}`. The goal is explicit user choice, not a hidden default.
### 3. Simplify Settings Screen ### 3. Simplify Settings Screen
- [ ] Remove the standalone "Test Connection" form/URL input at the top of settings. - [ ] Remove the standalone "Test Connection" form/URL input at the top of settings.
- [ ] Keep the per-host "Test" button in each host row (already exists). - [ ] Keep the per-host "Test" button in each host row (already exists).
@@ -49,5 +53,5 @@ The multi-daemon infrastructure is in place: session directory with daemon-scope
### 7. Home Screen Agent List ### 7. Home Screen Agent List
- [ ] Remove grouping of agents by host—show a single flat list. - [ ] Remove grouping of agents by host—show a single flat list.
- [ ] Each agent row displays its host name as metadata (badge, subtitle, etc.). - [ ] Each agent row displays its host name as metadata (badge, subtitle, etc.).
- [ ] Sort agents by recent activity or alphabetically (not by host). - [ ] Sort agents by recent activity or alphabetically (not by host).