feat(app): restore reload action for agent tabs
This commit is contained in:
@@ -84,6 +84,7 @@ interface SplitContainerProps {
|
|||||||
onCloseTab: (tabId: string) => Promise<void> | void;
|
onCloseTab: (tabId: string) => Promise<void> | void;
|
||||||
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
||||||
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
||||||
|
onReloadAgent: (agentId: string) => Promise<void> | void;
|
||||||
onCloseTabsToLeft: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
onCloseTabsToLeft: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
||||||
onCloseTabsToRight: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
onCloseTabsToRight: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
||||||
onCloseOtherTabs: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
onCloseOtherTabs: (tabId: string, paneTabs: WorkspaceTabDescriptor[]) => Promise<void> | void;
|
||||||
@@ -265,6 +266,7 @@ export function SplitContainer({
|
|||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTabsToLeft,
|
onCloseTabsToLeft,
|
||||||
onCloseTabsToRight,
|
onCloseTabsToRight,
|
||||||
onCloseOtherTabs,
|
onCloseOtherTabs,
|
||||||
@@ -534,6 +536,7 @@ export function SplitContainer({
|
|||||||
onCloseTab={onCloseTab}
|
onCloseTab={onCloseTab}
|
||||||
onCopyResumeCommand={onCopyResumeCommand}
|
onCopyResumeCommand={onCopyResumeCommand}
|
||||||
onCopyAgentId={onCopyAgentId}
|
onCopyAgentId={onCopyAgentId}
|
||||||
|
onReloadAgent={onReloadAgent}
|
||||||
onCloseTabsToLeft={onCloseTabsToLeft}
|
onCloseTabsToLeft={onCloseTabsToLeft}
|
||||||
onCloseTabsToRight={onCloseTabsToRight}
|
onCloseTabsToRight={onCloseTabsToRight}
|
||||||
onCloseOtherTabs={onCloseOtherTabs}
|
onCloseOtherTabs={onCloseOtherTabs}
|
||||||
@@ -656,6 +659,7 @@ function SplitNodeView({
|
|||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTabsToLeft,
|
onCloseTabsToLeft,
|
||||||
onCloseTabsToRight,
|
onCloseTabsToRight,
|
||||||
onCloseOtherTabs,
|
onCloseOtherTabs,
|
||||||
@@ -691,6 +695,7 @@ function SplitNodeView({
|
|||||||
onCloseTab={onCloseTab}
|
onCloseTab={onCloseTab}
|
||||||
onCopyResumeCommand={onCopyResumeCommand}
|
onCopyResumeCommand={onCopyResumeCommand}
|
||||||
onCopyAgentId={onCopyAgentId}
|
onCopyAgentId={onCopyAgentId}
|
||||||
|
onReloadAgent={onReloadAgent}
|
||||||
onCloseTabsToLeft={onCloseTabsToLeft}
|
onCloseTabsToLeft={onCloseTabsToLeft}
|
||||||
onCloseTabsToRight={onCloseTabsToRight}
|
onCloseTabsToRight={onCloseTabsToRight}
|
||||||
onCloseOtherTabs={onCloseOtherTabs}
|
onCloseOtherTabs={onCloseOtherTabs}
|
||||||
@@ -741,6 +746,7 @@ function SplitNodeView({
|
|||||||
onCloseTab={onCloseTab}
|
onCloseTab={onCloseTab}
|
||||||
onCopyResumeCommand={onCopyResumeCommand}
|
onCopyResumeCommand={onCopyResumeCommand}
|
||||||
onCopyAgentId={onCopyAgentId}
|
onCopyAgentId={onCopyAgentId}
|
||||||
|
onReloadAgent={onReloadAgent}
|
||||||
onCloseTabsToLeft={onCloseTabsToLeft}
|
onCloseTabsToLeft={onCloseTabsToLeft}
|
||||||
onCloseTabsToRight={onCloseTabsToRight}
|
onCloseTabsToRight={onCloseTabsToRight}
|
||||||
onCloseOtherTabs={onCloseOtherTabs}
|
onCloseOtherTabs={onCloseOtherTabs}
|
||||||
@@ -790,6 +796,7 @@ function SplitPaneView({
|
|||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTabsToLeft,
|
onCloseTabsToLeft,
|
||||||
onCloseTabsToRight,
|
onCloseTabsToRight,
|
||||||
onCloseOtherTabs,
|
onCloseOtherTabs,
|
||||||
@@ -901,6 +908,7 @@ function SplitPaneView({
|
|||||||
onCloseTab={onCloseTab}
|
onCloseTab={onCloseTab}
|
||||||
onCopyResumeCommand={onCopyResumeCommand}
|
onCopyResumeCommand={onCopyResumeCommand}
|
||||||
onCopyAgentId={onCopyAgentId}
|
onCopyAgentId={onCopyAgentId}
|
||||||
|
onReloadAgent={onReloadAgent}
|
||||||
onCloseTabsToLeft={(tabId) => onCloseTabsToLeft(tabId, paneTabs)}
|
onCloseTabsToLeft={(tabId) => onCloseTabsToLeft(tabId, paneTabs)}
|
||||||
onCloseTabsToRight={(tabId) => onCloseTabsToRight(tabId, paneTabs)}
|
onCloseTabsToRight={(tabId) => onCloseTabsToRight(tabId, paneTabs)}
|
||||||
onCloseOtherTabs={(tabId) => onCloseOtherTabs(tabId, paneTabs)}
|
onCloseOtherTabs={(tabId) => onCloseOtherTabs(tabId, paneTabs)}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
|
|||||||
import { StyleSheet, UnistylesRuntime, useUnistyles } from "react-native-unistyles";
|
import { StyleSheet, UnistylesRuntime, useUnistyles } from "react-native-unistyles";
|
||||||
import { Check, CheckCircle } from "lucide-react-native";
|
import { Check, CheckCircle } from "lucide-react-native";
|
||||||
import { BottomSheetBackdrop, BottomSheetModal, BottomSheetScrollView } from "@gorhom/bottom-sheet";
|
import { BottomSheetBackdrop, BottomSheetModal, BottomSheetScrollView } from "@gorhom/bottom-sheet";
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
|
|
||||||
// Keep parity with dropdown-menu action statuses.
|
// Keep parity with dropdown-menu action statuses.
|
||||||
export type ActionStatus = "idle" | "pending" | "success";
|
export type ActionStatus = "idle" | "pending" | "success";
|
||||||
@@ -595,6 +596,7 @@ export function ContextMenuItem({
|
|||||||
successLabel,
|
successLabel,
|
||||||
closeOnSelect = true,
|
closeOnSelect = true,
|
||||||
testID,
|
testID,
|
||||||
|
tooltip,
|
||||||
}: PropsWithChildren<{
|
}: PropsWithChildren<{
|
||||||
description?: string;
|
description?: string;
|
||||||
onSelect?: () => void;
|
onSelect?: () => void;
|
||||||
@@ -612,6 +614,7 @@ export function ContextMenuItem({
|
|||||||
successLabel?: string;
|
successLabel?: string;
|
||||||
closeOnSelect?: boolean;
|
closeOnSelect?: boolean;
|
||||||
testID?: string;
|
testID?: string;
|
||||||
|
tooltip?: string;
|
||||||
}>): ReactElement {
|
}>): ReactElement {
|
||||||
const { theme } = useUnistyles();
|
const { theme } = useUnistyles();
|
||||||
const { setOpen } = useContextMenuContext("ContextMenuItem");
|
const { setOpen } = useContextMenuContext("ContextMenuItem");
|
||||||
@@ -642,7 +645,7 @@ export function ContextMenuItem({
|
|||||||
<Check size={16} color={theme.colors.foregroundMuted} />
|
<Check size={16} color={theme.colors.foregroundMuted} />
|
||||||
) : null);
|
) : null);
|
||||||
|
|
||||||
return (
|
const content = (
|
||||||
<Pressable
|
<Pressable
|
||||||
testID={testID}
|
testID={testID}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
@@ -704,6 +707,19 @@ export function ContextMenuItem({
|
|||||||
{trailingContent ? <View style={styles.trailingSlot}>{trailingContent}</View> : null}
|
{trailingContent ? <View style={styles.trailingSlot}>{trailingContent}</View> : null}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!tooltip) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip delayDuration={250} enabledOnDesktop enabledOnMobile={false}>
|
||||||
|
<TooltipTrigger asChild>{content}</TooltipTrigger>
|
||||||
|
<TooltipContent side="right" align="center" offset={10}>
|
||||||
|
<Text style={styles.tooltipText}>{tooltip}</Text>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create((theme) => ({
|
const styles = StyleSheet.create((theme) => ({
|
||||||
@@ -762,6 +778,10 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
fontSize: theme.fontSize.xs,
|
fontSize: theme.fontSize.xs,
|
||||||
color: theme.colors.foregroundMuted,
|
color: theme.colors.foregroundMuted,
|
||||||
},
|
},
|
||||||
|
tooltipText: {
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
color: theme.colors.foreground,
|
||||||
|
},
|
||||||
item: {
|
item: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
import Animated, { Keyframe, runOnJS } from "react-native-reanimated";
|
import Animated, { Keyframe, runOnJS } from "react-native-reanimated";
|
||||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||||
import { Check, CheckCircle } from "lucide-react-native";
|
import { Check, CheckCircle } from "lucide-react-native";
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
|
|
||||||
// Action status for menu items with loading/success feedback
|
// Action status for menu items with loading/success feedback
|
||||||
export type ActionStatus = "idle" | "pending" | "success";
|
export type ActionStatus = "idle" | "pending" | "success";
|
||||||
@@ -471,6 +472,7 @@ export function DropdownMenuItem({
|
|||||||
successLabel,
|
successLabel,
|
||||||
closeOnSelect = true,
|
closeOnSelect = true,
|
||||||
testID,
|
testID,
|
||||||
|
tooltip,
|
||||||
}: PropsWithChildren<{
|
}: PropsWithChildren<{
|
||||||
description?: string;
|
description?: string;
|
||||||
onSelect?: () => void;
|
onSelect?: () => void;
|
||||||
@@ -491,6 +493,7 @@ export function DropdownMenuItem({
|
|||||||
successLabel?: string;
|
successLabel?: string;
|
||||||
closeOnSelect?: boolean;
|
closeOnSelect?: boolean;
|
||||||
testID?: string;
|
testID?: string;
|
||||||
|
tooltip?: string;
|
||||||
}>): ReactElement {
|
}>): ReactElement {
|
||||||
const { theme } = useUnistyles();
|
const { theme } = useUnistyles();
|
||||||
const { setOpen } = useDropdownMenuContext("DropdownMenuItem");
|
const { setOpen } = useDropdownMenuContext("DropdownMenuItem");
|
||||||
@@ -524,7 +527,7 @@ export function DropdownMenuItem({
|
|||||||
<Check size={16} color={theme.colors.foregroundMuted} />
|
<Check size={16} color={theme.colors.foregroundMuted} />
|
||||||
) : null);
|
) : null);
|
||||||
|
|
||||||
return (
|
const content = (
|
||||||
<Pressable
|
<Pressable
|
||||||
testID={testID}
|
testID={testID}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
@@ -586,6 +589,19 @@ export function DropdownMenuItem({
|
|||||||
{trailingContent ? <View style={styles.trailingSlot}>{trailingContent}</View> : null}
|
{trailingContent ? <View style={styles.trailingSlot}>{trailingContent}</View> : null}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!tooltip) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip delayDuration={250} enabledOnDesktop enabledOnMobile={false}>
|
||||||
|
<TooltipTrigger asChild>{content}</TooltipTrigger>
|
||||||
|
<TooltipContent side="right" align="center" offset={10}>
|
||||||
|
<Text style={styles.tooltipText}>{tooltip}</Text>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create((theme) => ({
|
const styles = StyleSheet.create((theme) => ({
|
||||||
@@ -630,6 +646,10 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
fontSize: theme.fontSize.xs,
|
fontSize: theme.fontSize.xs,
|
||||||
color: theme.colors.foregroundMuted,
|
color: theme.colors.foregroundMuted,
|
||||||
},
|
},
|
||||||
|
tooltipText: {
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
color: theme.colors.foreground,
|
||||||
|
},
|
||||||
item: {
|
item: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
ArrowRightToLine,
|
ArrowRightToLine,
|
||||||
Columns2,
|
Columns2,
|
||||||
Copy,
|
Copy,
|
||||||
|
RotateCw,
|
||||||
Rows2,
|
Rows2,
|
||||||
SquarePen,
|
SquarePen,
|
||||||
SquareTerminal,
|
SquareTerminal,
|
||||||
@@ -71,6 +72,7 @@ type WorkspaceDesktopTabsRowProps = {
|
|||||||
onCloseTab: (tabId: string) => Promise<void> | void;
|
onCloseTab: (tabId: string) => Promise<void> | void;
|
||||||
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
||||||
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
||||||
|
onReloadAgent: (agentId: string) => Promise<void> | void;
|
||||||
onCloseTabsToLeft: (tabId: string) => Promise<void> | void;
|
onCloseTabsToLeft: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsToRight: (tabId: string) => Promise<void> | void;
|
onCloseTabsToRight: (tabId: string) => Promise<void> | void;
|
||||||
onCloseOtherTabs: (tabId: string) => Promise<void> | void;
|
onCloseOtherTabs: (tabId: string) => Promise<void> | void;
|
||||||
@@ -291,11 +293,14 @@ function TabChip({
|
|||||||
disabled={entry.disabled}
|
disabled={entry.disabled}
|
||||||
destructive={entry.destructive}
|
destructive={entry.destructive}
|
||||||
onSelect={entry.onSelect}
|
onSelect={entry.onSelect}
|
||||||
|
tooltip={entry.tooltip}
|
||||||
leading={(() => {
|
leading={(() => {
|
||||||
const iconColor = theme.colors.foregroundMuted;
|
const iconColor = theme.colors.foregroundMuted;
|
||||||
switch (entry.icon) {
|
switch (entry.icon) {
|
||||||
case "copy":
|
case "copy":
|
||||||
return <Copy size={16} color={iconColor} />;
|
return <Copy size={16} color={iconColor} />;
|
||||||
|
case "rotate-cw":
|
||||||
|
return <RotateCw size={16} color={iconColor} />;
|
||||||
case "arrow-left-to-line":
|
case "arrow-left-to-line":
|
||||||
return <ArrowLeftToLine size={16} color={iconColor} />;
|
return <ArrowLeftToLine size={16} color={iconColor} />;
|
||||||
case "arrow-right-to-line":
|
case "arrow-right-to-line":
|
||||||
@@ -335,6 +340,7 @@ export function WorkspaceDesktopTabsRow({
|
|||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTabsToLeft,
|
onCloseTabsToLeft,
|
||||||
onCloseTabsToRight,
|
onCloseTabsToRight,
|
||||||
onCloseOtherTabs,
|
onCloseOtherTabs,
|
||||||
@@ -457,6 +463,7 @@ export function WorkspaceDesktopTabsRow({
|
|||||||
normalizedWorkspaceId={normalizedWorkspaceId}
|
normalizedWorkspaceId={normalizedWorkspaceId}
|
||||||
onCopyResumeCommand={onCopyResumeCommand}
|
onCopyResumeCommand={onCopyResumeCommand}
|
||||||
onCopyAgentId={onCopyAgentId}
|
onCopyAgentId={onCopyAgentId}
|
||||||
|
onReloadAgent={onReloadAgent}
|
||||||
onCloseTabsToLeft={onCloseTabsToLeft}
|
onCloseTabsToLeft={onCloseTabsToLeft}
|
||||||
onCloseTabsToRight={onCloseTabsToRight}
|
onCloseTabsToRight={onCloseTabsToRight}
|
||||||
onCloseOtherTabs={onCloseOtherTabs}
|
onCloseOtherTabs={onCloseOtherTabs}
|
||||||
@@ -585,6 +592,7 @@ function ResolvedDesktopTabChip({
|
|||||||
normalizedWorkspaceId,
|
normalizedWorkspaceId,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTabsToLeft,
|
onCloseTabsToLeft,
|
||||||
onCloseTabsToRight,
|
onCloseTabsToRight,
|
||||||
onCloseOtherTabs,
|
onCloseOtherTabs,
|
||||||
@@ -608,6 +616,7 @@ function ResolvedDesktopTabChip({
|
|||||||
normalizedWorkspaceId: string;
|
normalizedWorkspaceId: string;
|
||||||
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
||||||
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
||||||
|
onReloadAgent: (agentId: string) => Promise<void> | void;
|
||||||
onCloseTabsToLeft: (tabId: string) => Promise<void> | void;
|
onCloseTabsToLeft: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsToRight: (tabId: string) => Promise<void> | void;
|
onCloseTabsToRight: (tabId: string) => Promise<void> | void;
|
||||||
onCloseOtherTabs: (tabId: string) => Promise<void> | void;
|
onCloseOtherTabs: (tabId: string) => Promise<void> | void;
|
||||||
@@ -630,6 +639,7 @@ function ResolvedDesktopTabChip({
|
|||||||
tabCount,
|
tabCount,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCloseTabsToLeft,
|
onCloseTabsToLeft,
|
||||||
onCloseTabsToRight,
|
onCloseTabsToRight,
|
||||||
@@ -644,6 +654,7 @@ function ResolvedDesktopTabChip({
|
|||||||
onCloseTabsToRight,
|
onCloseTabsToRight,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
|
onReloadAgent,
|
||||||
tabCount,
|
tabCount,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
Ellipsis,
|
Ellipsis,
|
||||||
EllipsisVertical,
|
EllipsisVertical,
|
||||||
PanelRight,
|
PanelRight,
|
||||||
|
RotateCw,
|
||||||
SquarePen,
|
SquarePen,
|
||||||
SquareTerminal,
|
SquareTerminal,
|
||||||
X,
|
X,
|
||||||
@@ -182,6 +183,7 @@ type MobileWorkspaceTabSwitcherProps = {
|
|||||||
onSelectSwitcherTab: (key: string) => void;
|
onSelectSwitcherTab: (key: string) => void;
|
||||||
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
||||||
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
||||||
|
onReloadAgent: (agentId: string) => Promise<void> | void;
|
||||||
onCloseTab: (tabId: string) => Promise<void> | void;
|
onCloseTab: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsAbove: (tabId: string) => Promise<void> | void;
|
onCloseTabsAbove: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsBelow: (tabId: string) => Promise<void> | void;
|
onCloseTabsBelow: (tabId: string) => Promise<void> | void;
|
||||||
@@ -269,6 +271,7 @@ function MobileWorkspaceTabOption({
|
|||||||
onPress,
|
onPress,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCloseTabsAbove,
|
onCloseTabsAbove,
|
||||||
onCloseTabsBelow,
|
onCloseTabsBelow,
|
||||||
@@ -284,6 +287,7 @@ function MobileWorkspaceTabOption({
|
|||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
||||||
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
||||||
|
onReloadAgent: (agentId: string) => Promise<void> | void;
|
||||||
onCloseTab: (tabId: string) => Promise<void> | void;
|
onCloseTab: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsAbove: (tabId: string) => Promise<void> | void;
|
onCloseTabsAbove: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsBelow: (tabId: string) => Promise<void> | void;
|
onCloseTabsBelow: (tabId: string) => Promise<void> | void;
|
||||||
@@ -299,6 +303,7 @@ function MobileWorkspaceTabOption({
|
|||||||
menuTestIDBase,
|
menuTestIDBase,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCloseTabsBefore: onCloseTabsAbove,
|
onCloseTabsBefore: onCloseTabsAbove,
|
||||||
onCloseTabsAfter: onCloseTabsBelow,
|
onCloseTabsAfter: onCloseTabsBelow,
|
||||||
@@ -342,11 +347,14 @@ function MobileWorkspaceTabOption({
|
|||||||
disabled={entry.disabled}
|
disabled={entry.disabled}
|
||||||
destructive={entry.destructive}
|
destructive={entry.destructive}
|
||||||
onSelect={entry.onSelect}
|
onSelect={entry.onSelect}
|
||||||
|
tooltip={entry.tooltip}
|
||||||
leading={(() => {
|
leading={(() => {
|
||||||
const iconColor = theme.colors.foregroundMuted;
|
const iconColor = theme.colors.foregroundMuted;
|
||||||
switch (entry.icon) {
|
switch (entry.icon) {
|
||||||
case "copy":
|
case "copy":
|
||||||
return <Copy size={16} color={iconColor} />;
|
return <Copy size={16} color={iconColor} />;
|
||||||
|
case "rotate-cw":
|
||||||
|
return <RotateCw size={16} color={iconColor} />;
|
||||||
case "arrow-left-to-line":
|
case "arrow-left-to-line":
|
||||||
return <ArrowLeftToLine size={16} color={iconColor} />;
|
return <ArrowLeftToLine size={16} color={iconColor} />;
|
||||||
case "arrow-right-to-line":
|
case "arrow-right-to-line":
|
||||||
@@ -389,6 +397,7 @@ const MobileWorkspaceTabSwitcher = memo(function MobileWorkspaceTabSwitcher({
|
|||||||
onSelectSwitcherTab,
|
onSelectSwitcherTab,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCloseTabsAbove,
|
onCloseTabsAbove,
|
||||||
onCloseTabsBelow,
|
onCloseTabsBelow,
|
||||||
@@ -460,6 +469,7 @@ const MobileWorkspaceTabSwitcher = memo(function MobileWorkspaceTabSwitcher({
|
|||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
onCopyResumeCommand={onCopyResumeCommand}
|
onCopyResumeCommand={onCopyResumeCommand}
|
||||||
onCopyAgentId={onCopyAgentId}
|
onCopyAgentId={onCopyAgentId}
|
||||||
|
onReloadAgent={onReloadAgent}
|
||||||
onCloseTab={onCloseTab}
|
onCloseTab={onCloseTab}
|
||||||
onCloseTabsAbove={onCloseTabsAbove}
|
onCloseTabsAbove={onCloseTabsAbove}
|
||||||
onCloseTabsBelow={onCloseTabsBelow}
|
onCloseTabsBelow={onCloseTabsBelow}
|
||||||
@@ -1366,6 +1376,23 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
|
|||||||
[normalizedServerId, toast],
|
[normalizedServerId, toast],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleReloadAgent = useCallback(
|
||||||
|
async (agentId: string) => {
|
||||||
|
if (!client || !isConnected) {
|
||||||
|
toast.error("Host is not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await client.refreshAgent(agentId);
|
||||||
|
toast.show("Reloaded agent", { variant: "success" });
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(error instanceof Error ? error.message : "Failed to reload agent");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[client, isConnected, toast],
|
||||||
|
);
|
||||||
|
|
||||||
const handleCopyWorkspacePath = useCallback(async () => {
|
const handleCopyWorkspacePath = useCallback(async () => {
|
||||||
if (!isAbsolutePath(normalizedWorkspaceId)) {
|
if (!isAbsolutePath(normalizedWorkspaceId)) {
|
||||||
toast.error("Workspace path not available");
|
toast.error("Workspace path not available");
|
||||||
@@ -2211,6 +2238,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
|
|||||||
onSelectSwitcherTab={handleSelectSwitcherTab}
|
onSelectSwitcherTab={handleSelectSwitcherTab}
|
||||||
onCopyResumeCommand={handleCopyResumeCommand}
|
onCopyResumeCommand={handleCopyResumeCommand}
|
||||||
onCopyAgentId={handleCopyAgentId}
|
onCopyAgentId={handleCopyAgentId}
|
||||||
|
onReloadAgent={handleReloadAgent}
|
||||||
onCloseTab={handleCloseTabById}
|
onCloseTab={handleCloseTabById}
|
||||||
onCloseTabsAbove={handleCloseTabsToLeft}
|
onCloseTabsAbove={handleCloseTabsToLeft}
|
||||||
onCloseTabsBelow={handleCloseTabsToRight}
|
onCloseTabsBelow={handleCloseTabsToRight}
|
||||||
@@ -2231,6 +2259,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
|
|||||||
onCloseTab={handleCloseTabById}
|
onCloseTab={handleCloseTabById}
|
||||||
onCopyResumeCommand={handleCopyResumeCommand}
|
onCopyResumeCommand={handleCopyResumeCommand}
|
||||||
onCopyAgentId={handleCopyAgentId}
|
onCopyAgentId={handleCopyAgentId}
|
||||||
|
onReloadAgent={handleReloadAgent}
|
||||||
onCloseTabsToLeft={handleCloseTabsToLeft}
|
onCloseTabsToLeft={handleCloseTabsToLeft}
|
||||||
onCloseTabsToRight={handleCloseTabsToRight}
|
onCloseTabsToRight={handleCloseTabsToRight}
|
||||||
onCloseOtherTabs={handleCloseOtherTabs}
|
onCloseOtherTabs={handleCloseOtherTabs}
|
||||||
@@ -2267,6 +2296,7 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps)
|
|||||||
onCloseTab={handleCloseTabById}
|
onCloseTab={handleCloseTabById}
|
||||||
onCopyResumeCommand={handleCopyResumeCommand}
|
onCopyResumeCommand={handleCopyResumeCommand}
|
||||||
onCopyAgentId={handleCopyAgentId}
|
onCopyAgentId={handleCopyAgentId}
|
||||||
|
onReloadAgent={handleReloadAgent}
|
||||||
onCloseTabsToLeft={handleCloseTabsToLeftInPane}
|
onCloseTabsToLeft={handleCloseTabsToLeftInPane}
|
||||||
onCloseTabsToRight={handleCloseTabsToRightInPane}
|
onCloseTabsToRight={handleCloseTabsToRightInPane}
|
||||||
onCloseOtherTabs={handleCloseOtherTabsInPane}
|
onCloseOtherTabs={handleCloseOtherTabsInPane}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ describe("buildWorkspaceTabMenuEntries", () => {
|
|||||||
it("uses desktop tab ordering labels for desktop menus", () => {
|
it("uses desktop tab ordering labels for desktop menus", () => {
|
||||||
const onCopyResumeCommand = vi.fn();
|
const onCopyResumeCommand = vi.fn();
|
||||||
const onCopyAgentId = vi.fn();
|
const onCopyAgentId = vi.fn();
|
||||||
|
const onReloadAgent = vi.fn();
|
||||||
const onCloseTab = vi.fn();
|
const onCloseTab = vi.fn();
|
||||||
const onCloseTabsBefore = vi.fn();
|
const onCloseTabsBefore = vi.fn();
|
||||||
const onCloseTabsAfter = vi.fn();
|
const onCloseTabsAfter = vi.fn();
|
||||||
@@ -28,6 +29,7 @@ describe("buildWorkspaceTabMenuEntries", () => {
|
|||||||
menuTestIDBase: "workspace-tab-context-agent_123",
|
menuTestIDBase: "workspace-tab-context-agent_123",
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCloseTabsBefore,
|
onCloseTabsBefore,
|
||||||
onCloseTabsAfter,
|
onCloseTabsAfter,
|
||||||
@@ -37,6 +39,7 @@ describe("buildWorkspaceTabMenuEntries", () => {
|
|||||||
expect(entries.filter((entry) => entry.kind === "item").map((entry) => entry.label)).toEqual([
|
expect(entries.filter((entry) => entry.kind === "item").map((entry) => entry.label)).toEqual([
|
||||||
"Copy resume command",
|
"Copy resume command",
|
||||||
"Copy agent id",
|
"Copy agent id",
|
||||||
|
"Reload agent",
|
||||||
"Close to the left",
|
"Close to the left",
|
||||||
"Close to the right",
|
"Close to the right",
|
||||||
"Close other tabs",
|
"Close other tabs",
|
||||||
@@ -53,6 +56,7 @@ describe("buildWorkspaceTabMenuEntries", () => {
|
|||||||
menuTestIDBase: "workspace-tab-menu-agent_123",
|
menuTestIDBase: "workspace-tab-menu-agent_123",
|
||||||
onCopyResumeCommand: vi.fn(),
|
onCopyResumeCommand: vi.fn(),
|
||||||
onCopyAgentId: vi.fn(),
|
onCopyAgentId: vi.fn(),
|
||||||
|
onReloadAgent: vi.fn(),
|
||||||
onCloseTab: vi.fn(),
|
onCloseTab: vi.fn(),
|
||||||
onCloseTabsBefore: vi.fn(),
|
onCloseTabsBefore: vi.fn(),
|
||||||
onCloseTabsAfter: vi.fn(),
|
onCloseTabsAfter: vi.fn(),
|
||||||
@@ -62,6 +66,7 @@ describe("buildWorkspaceTabMenuEntries", () => {
|
|||||||
expect(entries.filter((entry) => entry.kind === "item").map((entry) => entry.label)).toEqual([
|
expect(entries.filter((entry) => entry.kind === "item").map((entry) => entry.label)).toEqual([
|
||||||
"Copy resume command",
|
"Copy resume command",
|
||||||
"Copy agent id",
|
"Copy agent id",
|
||||||
|
"Reload agent",
|
||||||
"Close tabs above",
|
"Close tabs above",
|
||||||
"Close tabs below",
|
"Close tabs below",
|
||||||
"Close other tabs",
|
"Close other tabs",
|
||||||
@@ -83,6 +88,7 @@ describe("buildWorkspaceTabMenuEntries", () => {
|
|||||||
menuTestIDBase: "workspace-tab-menu-draft_123",
|
menuTestIDBase: "workspace-tab-menu-draft_123",
|
||||||
onCopyResumeCommand: vi.fn(),
|
onCopyResumeCommand: vi.fn(),
|
||||||
onCopyAgentId: vi.fn(),
|
onCopyAgentId: vi.fn(),
|
||||||
|
onReloadAgent: vi.fn(),
|
||||||
onCloseTab: vi.fn(),
|
onCloseTab: vi.fn(),
|
||||||
onCloseTabsBefore: vi.fn(),
|
onCloseTabsBefore: vi.fn(),
|
||||||
onCloseTabsAfter: vi.fn(),
|
onCloseTabsAfter: vi.fn(),
|
||||||
@@ -92,6 +98,34 @@ describe("buildWorkspaceTabMenuEntries", () => {
|
|||||||
expect(entries.some((entry) => entry.kind === "item" && entry.label === "Copy agent id")).toBe(
|
expect(entries.some((entry) => entry.kind === "item" && entry.label === "Copy agent id")).toBe(
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
expect(entries.some((entry) => entry.kind === "item" && entry.label === "Reload agent")).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
expect(entries.some((entry) => entry.kind === "separator")).toBe(false);
|
expect(entries.some((entry) => entry.kind === "separator")).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("adds reload tooltip copy for agent tabs", () => {
|
||||||
|
const entries = buildWorkspaceTabMenuEntries({
|
||||||
|
surface: "desktop",
|
||||||
|
tab: createAgentTab(),
|
||||||
|
index: 0,
|
||||||
|
tabCount: 1,
|
||||||
|
menuTestIDBase: "workspace-tab-context-agent_123",
|
||||||
|
onCopyResumeCommand: vi.fn(),
|
||||||
|
onCopyAgentId: vi.fn(),
|
||||||
|
onReloadAgent: vi.fn(),
|
||||||
|
onCloseTab: vi.fn(),
|
||||||
|
onCloseTabsBefore: vi.fn(),
|
||||||
|
onCloseTabsAfter: vi.fn(),
|
||||||
|
onCloseOtherTabs: vi.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(entries).toContainEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
kind: "item",
|
||||||
|
key: "reload-agent",
|
||||||
|
tooltip: "Reload agent to update skills, MCPs or login status.",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,8 +8,15 @@ export type WorkspaceTabMenuEntry =
|
|||||||
kind: "item";
|
kind: "item";
|
||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
icon?: "copy" | "arrow-left-to-line" | "arrow-right-to-line" | "copy-x" | "x";
|
icon?:
|
||||||
|
| "copy"
|
||||||
|
| "rotate-cw"
|
||||||
|
| "arrow-left-to-line"
|
||||||
|
| "arrow-right-to-line"
|
||||||
|
| "copy-x"
|
||||||
|
| "x";
|
||||||
hint?: string;
|
hint?: string;
|
||||||
|
tooltip?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
destructive?: boolean;
|
destructive?: boolean;
|
||||||
testID: string;
|
testID: string;
|
||||||
@@ -28,6 +35,7 @@ interface BuildWorkspaceTabMenuEntriesInput {
|
|||||||
menuTestIDBase: string;
|
menuTestIDBase: string;
|
||||||
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
||||||
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
||||||
|
onReloadAgent: (agentId: string) => Promise<void> | void;
|
||||||
onCloseTab: (tabId: string) => Promise<void> | void;
|
onCloseTab: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsBefore: (tabId: string) => Promise<void> | void;
|
onCloseTabsBefore: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsAfter: (tabId: string) => Promise<void> | void;
|
onCloseTabsAfter: (tabId: string) => Promise<void> | void;
|
||||||
@@ -40,6 +48,7 @@ interface BuildWorkspaceDesktopTabActionsInput {
|
|||||||
tabCount: number;
|
tabCount: number;
|
||||||
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
onCopyResumeCommand: (agentId: string) => Promise<void> | void;
|
||||||
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
onCopyAgentId: (agentId: string) => Promise<void> | void;
|
||||||
|
onReloadAgent: (agentId: string) => Promise<void> | void;
|
||||||
onCloseTab: (tabId: string) => Promise<void> | void;
|
onCloseTab: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsToLeft: (tabId: string) => Promise<void> | void;
|
onCloseTabsToLeft: (tabId: string) => Promise<void> | void;
|
||||||
onCloseTabsToRight: (tabId: string) => Promise<void> | void;
|
onCloseTabsToRight: (tabId: string) => Promise<void> | void;
|
||||||
@@ -92,6 +101,7 @@ export function buildWorkspaceTabMenuEntries(
|
|||||||
menuTestIDBase,
|
menuTestIDBase,
|
||||||
onCopyResumeCommand,
|
onCopyResumeCommand,
|
||||||
onCopyAgentId,
|
onCopyAgentId,
|
||||||
|
onReloadAgent,
|
||||||
onCloseTab,
|
onCloseTab,
|
||||||
onCloseTabsBefore,
|
onCloseTabsBefore,
|
||||||
onCloseTabsAfter,
|
onCloseTabsAfter,
|
||||||
@@ -125,6 +135,17 @@ export function buildWorkspaceTabMenuEntries(
|
|||||||
void onCopyAgentId(agentId);
|
void onCopyAgentId(agentId);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
entries.push({
|
||||||
|
kind: "item",
|
||||||
|
key: "reload-agent",
|
||||||
|
label: "Reload agent",
|
||||||
|
icon: "rotate-cw",
|
||||||
|
tooltip: "Reload agent to update skills, MCPs or login status.",
|
||||||
|
testID: `${menuTestIDBase}-reload-agent`,
|
||||||
|
onSelect: () => {
|
||||||
|
void onReloadAgent(agentId);
|
||||||
|
},
|
||||||
|
});
|
||||||
entries.push({
|
entries.push({
|
||||||
kind: "separator",
|
kind: "separator",
|
||||||
key: "copy-separator",
|
key: "copy-separator",
|
||||||
@@ -192,6 +213,7 @@ export function buildWorkspaceDesktopTabActions(
|
|||||||
menuTestIDBase: contextMenuTestId,
|
menuTestIDBase: contextMenuTestId,
|
||||||
onCopyResumeCommand: input.onCopyResumeCommand,
|
onCopyResumeCommand: input.onCopyResumeCommand,
|
||||||
onCopyAgentId: input.onCopyAgentId,
|
onCopyAgentId: input.onCopyAgentId,
|
||||||
|
onReloadAgent: input.onReloadAgent,
|
||||||
onCloseTab: input.onCloseTab,
|
onCloseTab: input.onCloseTab,
|
||||||
onCloseTabsBefore: input.onCloseTabsToLeft,
|
onCloseTabsBefore: input.onCloseTabsToLeft,
|
||||||
onCloseTabsAfter: input.onCloseTabsToRight,
|
onCloseTabsAfter: input.onCloseTabsToRight,
|
||||||
|
|||||||
Reference in New Issue
Block a user