fix(app): resolve terminal profiles at creation boundary
Profile placeholders were reaching spawned processes because each menu decided whether to resolve them. Keep UI callers profile-only and perform empty-prompt resolution once when the workspace terminal is created.
This commit is contained in:
@@ -69,7 +69,7 @@ import {
|
||||
WorkspaceDesktopTabsRow,
|
||||
type WorkspaceDesktopTabRowItem,
|
||||
} from "@/screens/workspace/workspace-desktop-tabs-row";
|
||||
import type { TerminalProfileInput } from "@/screens/workspace/terminals/use-workspace-terminals";
|
||||
import type { TerminalProfile } from "@getpaseo/protocol/messages";
|
||||
import {
|
||||
WorkspaceTabPresentationResolver,
|
||||
WorkspaceTabIcon,
|
||||
@@ -111,7 +111,7 @@ interface SplitContainerProps {
|
||||
onCloseTabsToRight: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
||||
onCloseOtherTabs: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
||||
onCreateDraftTab: (input: { paneId?: string }) => void;
|
||||
onCreateTerminalTab: (input: { paneId?: string; profile?: TerminalProfileInput }) => void;
|
||||
onCreateTerminalTab: (input: { paneId?: string; profile?: TerminalProfile }) => void;
|
||||
onCreateBrowserTab: (input: { paneId?: string }) => void;
|
||||
showCreateBrowserTab?: boolean;
|
||||
buildPaneContentModel: (input: {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
|
||||
import type { TerminalProfile } from "@getpaseo/protocol/messages";
|
||||
import { resolveTerminalProfileLaunch } from "@getpaseo/protocol/terminal-profiles";
|
||||
import type { WorkspaceDescriptor } from "@/stores/session-store";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useReplicaQuery } from "@/data/query";
|
||||
@@ -17,19 +19,11 @@ import {
|
||||
upsertCreatedTerminalPayload,
|
||||
} from "@/screens/workspace/terminals/state";
|
||||
|
||||
interface TerminalProfileInput {
|
||||
name: string;
|
||||
command: string;
|
||||
args?: string[];
|
||||
}
|
||||
|
||||
interface PendingTerminalCreateInput {
|
||||
paneId?: string;
|
||||
profile?: TerminalProfileInput;
|
||||
profile?: TerminalProfile;
|
||||
}
|
||||
|
||||
export type { TerminalProfileInput };
|
||||
|
||||
interface UseWorkspaceTerminalsInput {
|
||||
client: DaemonClient | null;
|
||||
isConnected: boolean;
|
||||
@@ -135,10 +129,13 @@ export function useWorkspaceTerminals(input: UseWorkspaceTerminalsInput) {
|
||||
if (!client || !workspaceDirectory) {
|
||||
throw new Error(t("workspace.terminal.hostDisconnected"));
|
||||
}
|
||||
const payload = _input?.profile
|
||||
? await client.createTerminal(workspaceDirectory, _input.profile.name, undefined, {
|
||||
command: _input.profile.command,
|
||||
args: _input.profile.args,
|
||||
const profile = _input?.profile
|
||||
? resolveTerminalProfileLaunch(_input.profile, "")
|
||||
: undefined;
|
||||
const payload = profile
|
||||
? await client.createTerminal(workspaceDirectory, profile.name, undefined, {
|
||||
command: profile.command,
|
||||
args: profile.args,
|
||||
workspaceId: normalizedWorkspaceId || undefined,
|
||||
})
|
||||
: await client.createTerminal(workspaceDirectory, undefined, undefined, {
|
||||
|
||||
@@ -96,7 +96,7 @@ import {
|
||||
resolveTerminalProfiles,
|
||||
} from "@getpaseo/protocol/terminal-profiles";
|
||||
import { buildSettingsHostSectionRoute } from "@/utils/host-routes";
|
||||
import type { TerminalProfileInput } from "@/screens/workspace/terminals/use-workspace-terminals";
|
||||
import type { TerminalProfile } from "@getpaseo/protocol/messages";
|
||||
import { TerminalProfileIcon } from "@/components/terminal-profile-icon";
|
||||
import { useWorkspaceLayoutStore } from "@/stores/workspace-layout-store";
|
||||
import { buildWorkspaceTabPersistenceKey } from "@/workspace-tabs/model";
|
||||
@@ -261,7 +261,7 @@ function TabLabelMeasurement({
|
||||
interface TerminalProfileMenuItemProps {
|
||||
profile: { id: string; name: string; command: string; args?: string[]; icon?: string };
|
||||
disabled?: boolean;
|
||||
onLaunch: (profile: TerminalProfileInput) => void;
|
||||
onLaunch: (profile: TerminalProfile) => void;
|
||||
}
|
||||
|
||||
function TerminalProfileMenuItem({ profile, disabled, onLaunch }: TerminalProfileMenuItemProps) {
|
||||
@@ -286,7 +286,7 @@ interface TabTargetLauncherOptions {
|
||||
onOpenChanges: () => void;
|
||||
onOpenFiles: () => void;
|
||||
onOpenPullRequest: () => void;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfileInput) => void;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfile) => void;
|
||||
}
|
||||
|
||||
interface WorkspaceNewTabButtonProps extends TabTargetLauncherOptions {
|
||||
@@ -660,7 +660,7 @@ interface WorkspaceDesktopTabsRowProps {
|
||||
onCloseTabsToRight: (tabId: string) => Promise<void> | void;
|
||||
onCloseOtherTabs: (tabId: string) => Promise<void> | void;
|
||||
onCreateDraftTab: (input: { paneId?: string }) => void;
|
||||
onCreateTerminalTab: (input: { paneId?: string; profile?: TerminalProfileInput }) => void;
|
||||
onCreateTerminalTab: (input: { paneId?: string; profile?: TerminalProfile }) => void;
|
||||
onCreateBrowserTab: (input: { paneId?: string }) => void;
|
||||
showCreateBrowserTab?: boolean;
|
||||
disableCreateTerminal?: boolean;
|
||||
@@ -1396,7 +1396,7 @@ function ResolvedWorkspaceDesktopTabsRow({
|
||||
}, [onCreateTerminalTab, paneId]);
|
||||
|
||||
const handleCreateTerminalWithProfile = useCallback(
|
||||
(profile: TerminalProfileInput) => {
|
||||
(profile: TerminalProfile) => {
|
||||
onCreateTerminalTab({ paneId, profile });
|
||||
},
|
||||
[onCreateTerminalTab, paneId],
|
||||
|
||||
@@ -180,13 +180,10 @@ import {
|
||||
buildSettingsHostRoute,
|
||||
buildSettingsHostSectionRoute,
|
||||
} from "@/utils/host-routes";
|
||||
import {
|
||||
useWorkspaceTerminals,
|
||||
type TerminalProfileInput,
|
||||
} from "@/screens/workspace/terminals/use-workspace-terminals";
|
||||
import { useWorkspaceTerminals } from "@/screens/workspace/terminals/use-workspace-terminals";
|
||||
import type { TerminalProfile } from "@getpaseo/protocol/messages";
|
||||
import { useDaemonConfig } from "@/hooks/use-daemon-config";
|
||||
import {
|
||||
resolveTerminalProfileLaunch,
|
||||
getTerminalProfileIcon,
|
||||
resolveTerminalProfiles,
|
||||
} from "@getpaseo/protocol/terminal-profiles";
|
||||
@@ -930,7 +927,7 @@ interface WorkspaceHeaderMenuProps {
|
||||
menuSettingsIcon: ReactElement;
|
||||
onCreateDraftTab: () => void;
|
||||
onCreateTerminal: () => void;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfileInput) => void;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfile) => void;
|
||||
onCreateBrowser: () => void;
|
||||
onOpenImportSheet: () => void;
|
||||
onCopyWorkspacePath: () => void;
|
||||
@@ -940,7 +937,7 @@ interface WorkspaceHeaderMenuProps {
|
||||
interface HeaderMenuProfileItemProps {
|
||||
profile: { id: string; name: string; command: string; args?: string[]; icon?: string };
|
||||
disabled: boolean;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfileInput) => void;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfile) => void;
|
||||
}
|
||||
|
||||
function HeaderMenuProfileItem({
|
||||
@@ -949,7 +946,7 @@ function HeaderMenuProfileItem({
|
||||
onCreateTerminalWithProfile,
|
||||
}: HeaderMenuProfileItemProps) {
|
||||
const handleSelect = useCallback(() => {
|
||||
onCreateTerminalWithProfile(resolveTerminalProfileLaunch(profile, ""));
|
||||
onCreateTerminalWithProfile(profile);
|
||||
}, [onCreateTerminalWithProfile, profile]);
|
||||
|
||||
const icon = getTerminalProfileIcon(profile);
|
||||
@@ -1196,7 +1193,7 @@ interface WorkspaceHeaderTitleBarProps {
|
||||
menuSettingsIcon: ReactElement;
|
||||
onCreateDraftTab: () => void;
|
||||
onCreateTerminal: () => void;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfileInput) => void;
|
||||
onCreateTerminalWithProfile: (profile: TerminalProfile) => void;
|
||||
onCreateBrowser: () => void;
|
||||
onOpenImportSheet: () => void;
|
||||
onCopyWorkspacePath: () => void;
|
||||
@@ -2604,7 +2601,7 @@ function WorkspaceScreenContent({
|
||||
const handleCreateTerminal = useStableEvent(createTerminal);
|
||||
|
||||
const handleCreateTerminalWithProfile = useCallback(
|
||||
(profile: TerminalProfileInput) => {
|
||||
(profile: TerminalProfile) => {
|
||||
createTerminal({ profile });
|
||||
},
|
||||
[createTerminal],
|
||||
|
||||
Reference in New Issue
Block a user