WIP: snapshot workspace execution refactor baseline
This commit is contained in:
@@ -36,6 +36,11 @@ function LauncherPanel() {
|
||||
const { serverId, workspaceId, target, retargetCurrentTab, isPaneFocused } = usePaneContext();
|
||||
const client = useHostRuntimeClient(serverId);
|
||||
const isConnected = useHostRuntimeIsConnected(serverId);
|
||||
const workspaceDirectory = useSessionStore(
|
||||
(state) =>
|
||||
state.sessions[serverId]?.workspaces.get(workspaceId)?.workspaceDirectory ??
|
||||
state.sessions[serverId]?.workspaces.get(workspaceId)?.projectRootPath,
|
||||
);
|
||||
const { providers, recordUsage } = useProviderRecency();
|
||||
const setAgents = useSessionStore((state) => state.setAgents);
|
||||
const [pendingAction, setPendingAction] = useState<string | null>(null);
|
||||
@@ -53,8 +58,8 @@ function LauncherPanel() {
|
||||
|
||||
const launchTerminalAgent = useCallback(
|
||||
async (providerId: AgentProvider) => {
|
||||
if (!client || !isConnected) {
|
||||
setErrorMessage("Host is not connected");
|
||||
if (!client || !isConnected || !workspaceDirectory) {
|
||||
setErrorMessage(!workspaceDirectory ? "Workspace directory not found" : "Host is not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -64,7 +69,7 @@ function LauncherPanel() {
|
||||
try {
|
||||
const agent = await client.createAgent({
|
||||
provider: providerId,
|
||||
cwd: workspaceId,
|
||||
cwd: workspaceDirectory,
|
||||
terminal: true,
|
||||
});
|
||||
recordUsage(providerId);
|
||||
@@ -82,7 +87,7 @@ function LauncherPanel() {
|
||||
setPendingAction((current) => (current === providerId ? null : current));
|
||||
}
|
||||
},
|
||||
[client, isConnected, recordUsage, retargetCurrentTab, serverId, setAgents, workspaceId],
|
||||
[client, isConnected, recordUsage, retargetCurrentTab, serverId, setAgents, workspaceDirectory],
|
||||
);
|
||||
|
||||
const openDraftTab = useCallback(() => {
|
||||
@@ -96,8 +101,8 @@ function LauncherPanel() {
|
||||
}, [retargetCurrentTab]);
|
||||
|
||||
const openTerminalTab = useCallback(async () => {
|
||||
if (!client || !isConnected) {
|
||||
setErrorMessage("Host is not connected");
|
||||
if (!client || !isConnected || !workspaceDirectory) {
|
||||
setErrorMessage(!workspaceDirectory ? "Workspace directory not found" : "Host is not connected");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,7 +110,7 @@ function LauncherPanel() {
|
||||
setErrorMessage(null);
|
||||
|
||||
try {
|
||||
const payload = await client.createTerminal(workspaceId);
|
||||
const payload = await client.createTerminal(workspaceDirectory);
|
||||
if (payload.error || !payload.terminal) {
|
||||
throw new Error(payload.error ?? "Failed to open terminal");
|
||||
}
|
||||
@@ -118,10 +123,20 @@ function LauncherPanel() {
|
||||
} finally {
|
||||
setPendingAction((current) => (current === "terminal" ? null : current));
|
||||
}
|
||||
}, [client, isConnected, retargetCurrentTab, workspaceId]);
|
||||
}, [client, isConnected, retargetCurrentTab, workspaceDirectory]);
|
||||
|
||||
const actionsDisabled = pendingAction !== null;
|
||||
|
||||
if (!workspaceDirectory) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={[styles.content, styles.loadingContent]}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView
|
||||
@@ -339,6 +354,9 @@ const styles = StyleSheet.create((theme) => ({
|
||||
paddingHorizontal: theme.spacing[4],
|
||||
paddingVertical: theme.spacing[8],
|
||||
},
|
||||
loadingContent: {
|
||||
flex: 1,
|
||||
},
|
||||
contentUnfocused: {
|
||||
opacity: 0.96,
|
||||
},
|
||||
|
||||
@@ -24,14 +24,20 @@ function useTerminalPanelDescriptor(
|
||||
context: { serverId: string; workspaceId: string },
|
||||
): PanelDescriptor {
|
||||
const client = useSessionStore((state) => state.sessions[context.serverId]?.client ?? null);
|
||||
const workspaceDirectory = useSessionStore(
|
||||
(state) =>
|
||||
state.sessions[context.serverId]?.workspaces.get(context.workspaceId)?.workspaceDirectory ??
|
||||
state.sessions[context.serverId]?.workspaces.get(context.workspaceId)?.projectRootPath ??
|
||||
null,
|
||||
);
|
||||
const terminalsQuery = useQuery({
|
||||
queryKey: ["terminals", context.serverId, context.workspaceId] as const,
|
||||
enabled: Boolean(client && context.workspaceId),
|
||||
queryKey: ["terminals", context.serverId, workspaceDirectory] as const,
|
||||
enabled: Boolean(client && workspaceDirectory),
|
||||
queryFn: async (): Promise<ListTerminalsPayload> => {
|
||||
if (!client) {
|
||||
return { cwd: context.workspaceId, terminals: [], requestId: "missing-client" };
|
||||
if (!client || !workspaceDirectory) {
|
||||
return { cwd: workspaceDirectory ?? "", terminals: [], requestId: "missing-client" };
|
||||
}
|
||||
return client.listTerminals(context.workspaceId);
|
||||
return client.listTerminals(workspaceDirectory);
|
||||
},
|
||||
staleTime: 5_000,
|
||||
});
|
||||
@@ -50,16 +56,22 @@ function useTerminalPanelDescriptor(
|
||||
function TerminalPanel() {
|
||||
const isFocused = useIsFocused();
|
||||
const { serverId, workspaceId, target, isPaneFocused } = usePaneContext();
|
||||
const workspaceDirectory = useSessionStore(
|
||||
(state) =>
|
||||
state.sessions[serverId]?.workspaces.get(workspaceId)?.workspaceDirectory ??
|
||||
state.sessions[serverId]?.workspaces.get(workspaceId)?.projectRootPath ??
|
||||
null,
|
||||
);
|
||||
invariant(target.kind === "terminal", "TerminalPanel requires terminal target");
|
||||
|
||||
if (!isFocused) {
|
||||
if (!isFocused || !workspaceDirectory) {
|
||||
return <View style={{ flex: 1 }} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<TerminalPane
|
||||
serverId={serverId}
|
||||
cwd={workspaceId}
|
||||
cwd={workspaceDirectory}
|
||||
terminalId={target.terminalId}
|
||||
isPaneFocused={isPaneFocused}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user