Remove active host dependency from UI actions
This commit is contained in:
@@ -6,7 +6,6 @@ import type { Agent } from "@/contexts/session-context";
|
||||
import { formatTimeAgo } from "@/utils/time";
|
||||
import { getAgentStatusColor, getAgentStatusLabel } from "@/utils/agent-status";
|
||||
import { getAgentProviderDefinition } from "@server/server/agent/provider-manifest";
|
||||
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
|
||||
import { type AggregatedAgentGroup } from "@/hooks/use-aggregated-agents";
|
||||
import { useDaemonSession } from "@/hooks/use-daemon-session";
|
||||
|
||||
@@ -16,7 +15,6 @@ interface AgentListProps {
|
||||
|
||||
export function AgentList({ agentGroups }: AgentListProps) {
|
||||
const { theme } = useUnistyles();
|
||||
const { setActiveDaemonId } = useDaemonConnections();
|
||||
const [actionAgent, setActionAgent] = useState<Agent | null>(null);
|
||||
const [actionAgentServerId, setActionAgentServerId] = useState<string | null>(null);
|
||||
const actionSession = useDaemonSession(actionAgentServerId ?? undefined, {
|
||||
@@ -28,19 +26,21 @@ export function AgentList({ agentGroups }: AgentListProps) {
|
||||
const isActionSheetVisible = actionAgent !== null;
|
||||
const isActionDaemonUnavailable = Boolean(actionAgentServerId && !actionSession);
|
||||
|
||||
const handleAgentPress = useCallback((serverId: string, agentId: string) => {
|
||||
if (isActionSheetVisible) {
|
||||
return;
|
||||
}
|
||||
setActiveDaemonId(serverId, { source: "agent_row_press" });
|
||||
router.push({
|
||||
pathname: "/agent/[serverId]/[agentId]",
|
||||
params: {
|
||||
serverId,
|
||||
agentId,
|
||||
},
|
||||
});
|
||||
}, [isActionSheetVisible, setActiveDaemonId]);
|
||||
const handleAgentPress = useCallback(
|
||||
(serverId: string, agentId: string) => {
|
||||
if (isActionSheetVisible) {
|
||||
return;
|
||||
}
|
||||
router.push({
|
||||
pathname: "/agent/[serverId]/[agentId]",
|
||||
params: {
|
||||
serverId,
|
||||
agentId,
|
||||
},
|
||||
});
|
||||
},
|
||||
[isActionSheetVisible]
|
||||
);
|
||||
|
||||
const handleAgentLongPress = useCallback((serverId: string, agent: Agent) => {
|
||||
setActionAgentServerId(serverId);
|
||||
|
||||
@@ -215,17 +215,14 @@ function AgentFlowModal({
|
||||
const isCreateFlow = !isImportFlow;
|
||||
|
||||
const { recentPaths, addRecentPath } = useRecentPaths();
|
||||
const { connectionStates, activeDaemonId, setActiveDaemonId } = useDaemonConnections();
|
||||
const { connectionStates } = useDaemonConnections();
|
||||
const daemonEntries = useMemo(() => Array.from(connectionStates.values()), [connectionStates]);
|
||||
const initialServerId = useMemo(() => {
|
||||
if (serverId) {
|
||||
return serverId;
|
||||
}
|
||||
if (activeDaemonId) {
|
||||
return activeDaemonId;
|
||||
}
|
||||
return daemonEntries[0]?.daemon.id ?? null;
|
||||
}, [serverId, activeDaemonId, daemonEntries]);
|
||||
}, [serverId, daemonEntries]);
|
||||
const [selectedServerId, setSelectedServerId] = useState<string | null>(initialServerId);
|
||||
const activeSession = useSession();
|
||||
const selectedSession = useSessionForServer(selectedServerId);
|
||||
@@ -308,8 +305,8 @@ function AgentFlowModal({
|
||||
} = gitRepoInfoRequest;
|
||||
const isWsConnected = ws?.isConnected ?? false;
|
||||
const router = useRouter();
|
||||
const activeServerId = session?.serverId ?? null;
|
||||
const selectedDaemonId = selectedServerId ?? activeServerId;
|
||||
const sessionServerId = session?.serverId ?? null;
|
||||
const selectedDaemonId = selectedServerId ?? sessionServerId;
|
||||
const selectedDaemonConnection = selectedDaemonId
|
||||
? connectionStates.get(selectedDaemonId)
|
||||
: null;
|
||||
@@ -330,8 +327,6 @@ function AgentFlowModal({
|
||||
const selectedDaemonStatusLabel = formatConnectionStatus(selectedDaemonStatus);
|
||||
const selectedDaemonIsUnavailable =
|
||||
!session || selectedDaemonStatus !== "online" || !ws?.isConnected;
|
||||
const isBackgroundDaemonTarget =
|
||||
Boolean(selectedDaemonId && activeDaemonId && selectedDaemonId !== activeDaemonId);
|
||||
const selectedDaemonLastError = selectedDaemonConnection?.lastError?.trim();
|
||||
const daemonAvailabilityError = selectedDaemonIsUnavailable
|
||||
? `${selectedDaemonLabel} is ${selectedDaemonStatusLabel}. Connect to it before creating or importing agents.${
|
||||
@@ -407,6 +402,7 @@ function AgentFlowModal({
|
||||
typeof InteractionManager.runAfterInteractions
|
||||
> | null>(null);
|
||||
const pendingNavigationAgentIdRef = useRef<string | null>(null);
|
||||
const pendingNavigationServerIdRef = useRef<string | null>(null);
|
||||
const openDropdownSheet = useCallback((key: DropdownKey) => {
|
||||
setOpenDropdown(key);
|
||||
}, []);
|
||||
@@ -862,45 +858,17 @@ function AgentFlowModal({
|
||||
type: "offline_daemon_action_attempt",
|
||||
action,
|
||||
daemonId: selectedDaemonId,
|
||||
activeDaemonId,
|
||||
status: selectedDaemonStatus ?? null,
|
||||
isBackground: isBackgroundDaemonTarget,
|
||||
reason: reason ?? daemonAvailabilityError,
|
||||
});
|
||||
},
|
||||
[
|
||||
activeDaemonId,
|
||||
daemonAvailabilityError,
|
||||
isBackgroundDaemonTarget,
|
||||
selectedDaemonId,
|
||||
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(() => {
|
||||
setInitialPrompt("");
|
||||
promptBaselineHeightRef.current = null;
|
||||
@@ -918,6 +886,7 @@ function AgentFlowModal({
|
||||
resetRepoInfo();
|
||||
setOpenDropdown(null);
|
||||
pendingRequestIdRef.current = null;
|
||||
pendingNavigationServerIdRef.current = null;
|
||||
shouldSyncBaseBranchRef.current = true;
|
||||
dictationRequestIdRef.current = null;
|
||||
setIsDictating(false);
|
||||
@@ -1024,24 +993,23 @@ function AgentFlowModal({
|
||||
|
||||
const navigateToAgentIfNeeded = useCallback(() => {
|
||||
const agentId = pendingNavigationAgentIdRef.current;
|
||||
if (!agentId || !activeServerId) {
|
||||
const targetServerId = pendingNavigationServerIdRef.current ?? selectedDaemonId;
|
||||
if (!agentId || !targetServerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
pendingNavigationAgentIdRef.current = null;
|
||||
if (activeDaemonId !== activeServerId) {
|
||||
setActiveDaemonId(activeServerId, { source: "agent_create_resume_nav" });
|
||||
}
|
||||
pendingNavigationServerIdRef.current = null;
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
router.push({
|
||||
pathname: "/agent/[serverId]/[agentId]",
|
||||
params: {
|
||||
serverId: activeServerId,
|
||||
serverId: targetServerId,
|
||||
agentId,
|
||||
},
|
||||
});
|
||||
});
|
||||
}, [activeDaemonId, activeServerId, router, setActiveDaemonId]);
|
||||
}, [router, selectedDaemonId]);
|
||||
|
||||
const handleSelectServer = useCallback((serverId: string) => {
|
||||
setSelectedServerId(serverId);
|
||||
@@ -1408,6 +1376,7 @@ function AgentFlowModal({
|
||||
const requestId = generateMessageId();
|
||||
|
||||
pendingRequestIdRef.current = requestId;
|
||||
pendingNavigationServerIdRef.current = selectedDaemonId ?? null;
|
||||
setIsLoading(true);
|
||||
setErrorMessage("");
|
||||
|
||||
@@ -1443,14 +1412,6 @@ function AgentFlowModal({
|
||||
}
|
||||
: undefined;
|
||||
|
||||
logBackgroundAgentAction("create", {
|
||||
cwd: trimmedPath,
|
||||
provider: selectedProvider,
|
||||
modeId,
|
||||
model: trimmedModel,
|
||||
baseBranch: trimmedBaseBranch || undefined,
|
||||
});
|
||||
|
||||
try {
|
||||
createAgent({
|
||||
config,
|
||||
@@ -1463,6 +1424,7 @@ function AgentFlowModal({
|
||||
setErrorMessage("Failed to create agent. Please try again.");
|
||||
setIsLoading(false);
|
||||
pendingRequestIdRef.current = null;
|
||||
pendingNavigationServerIdRef.current = null;
|
||||
}
|
||||
}, [
|
||||
workingDir,
|
||||
@@ -1475,7 +1437,6 @@ function AgentFlowModal({
|
||||
repoInfo,
|
||||
selectedMode,
|
||||
modeOptions,
|
||||
logBackgroundAgentAction,
|
||||
logOfflineDaemonAction,
|
||||
selectedProvider,
|
||||
isLoading,
|
||||
@@ -1484,6 +1445,7 @@ function AgentFlowModal({
|
||||
createAgent,
|
||||
daemonAvailabilityError,
|
||||
isTargetDaemonReady,
|
||||
selectedDaemonId,
|
||||
]);
|
||||
|
||||
const handleImportCandidatePress = useCallback(
|
||||
@@ -1499,13 +1461,10 @@ function AgentFlowModal({
|
||||
);
|
||||
return;
|
||||
}
|
||||
logBackgroundAgentAction("resume", {
|
||||
cwd: candidate.cwd,
|
||||
provider: candidate.provider,
|
||||
});
|
||||
setErrorMessage("");
|
||||
const requestId = generateMessageId();
|
||||
pendingRequestIdRef.current = requestId;
|
||||
pendingNavigationServerIdRef.current = selectedDaemonId ?? null;
|
||||
setIsLoading(true);
|
||||
resumeAgent({
|
||||
handle: candidate.persistence,
|
||||
@@ -1515,10 +1474,10 @@ function AgentFlowModal({
|
||||
[
|
||||
daemonAvailabilityError,
|
||||
isLoading,
|
||||
logBackgroundAgentAction,
|
||||
logOfflineDaemonAction,
|
||||
isTargetDaemonReady,
|
||||
resumeAgent,
|
||||
selectedDaemonId,
|
||||
setImportError,
|
||||
]
|
||||
);
|
||||
@@ -1603,6 +1562,7 @@ function AgentFlowModal({
|
||||
return;
|
||||
}
|
||||
pendingRequestIdRef.current = null;
|
||||
pendingNavigationServerIdRef.current = null;
|
||||
setIsLoading(false);
|
||||
setErrorMessage(
|
||||
payload.error ??
|
||||
|
||||
@@ -7,7 +7,6 @@ import { AudioLines, Users, Plus, Download } from "lucide-react-native";
|
||||
import { useRealtime } from "@/contexts/realtime-context";
|
||||
import { useSession } from "@/contexts/session-context";
|
||||
import { useFooterControls, FOOTER_HEIGHT } from "@/contexts/footer-controls-context";
|
||||
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
|
||||
import { RealtimeControls } from "./realtime-controls";
|
||||
import { CreateAgentModal, ImportAgentModal } from "./create-agent-modal";
|
||||
import Animated, {
|
||||
@@ -24,7 +23,6 @@ export function GlobalFooter() {
|
||||
const router = useRouter();
|
||||
const { isRealtimeMode, startRealtime } = useRealtime();
|
||||
const { ws } = useSession();
|
||||
const { activeDaemonId } = useDaemonConnections();
|
||||
const { controls } = useFooterControls();
|
||||
const [showCreateModal, setShowCreateModal] = useState(false);
|
||||
const [showImportModal, setShowImportModal] = useState(false);
|
||||
@@ -188,12 +186,10 @@ export function GlobalFooter() {
|
||||
<CreateAgentModal
|
||||
isVisible={showCreateModal}
|
||||
onClose={() => setShowCreateModal(false)}
|
||||
serverId={activeDaemonId}
|
||||
/>
|
||||
<ImportAgentModal
|
||||
isVisible={showImportModal}
|
||||
onClose={() => setShowImportModal(false)}
|
||||
serverId={activeDaemonId}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user