mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
feat: add setting to toggle task titles
This commit is contained in:
parent
1524d66ee4
commit
f14b9683dd
15 changed files with 147 additions and 37 deletions
|
|
@ -193,6 +193,7 @@ export const globalSettingsSchema = z.object({
|
|||
* @default "send"
|
||||
*/
|
||||
enterBehavior: z.enum(["send", "newline"]).optional(),
|
||||
taskTitlesEnabled: z.boolean().optional(),
|
||||
profileThresholds: z.record(z.string(), z.number()).optional(),
|
||||
hasOpenedModeSelector: z.boolean().optional(),
|
||||
lastModeExportPath: z.string().optional(),
|
||||
|
|
|
|||
|
|
@ -262,6 +262,7 @@ export type ExtensionState = Pick<
|
|||
| "includeCurrentCost"
|
||||
| "maxGitStatusFiles"
|
||||
| "requestDelaySeconds"
|
||||
| "taskTitlesEnabled"
|
||||
> & {
|
||||
version: string
|
||||
clineMessages: ClineMessage[]
|
||||
|
|
@ -302,6 +303,7 @@ export type ExtensionState = Pick<
|
|||
renderContext: "sidebar" | "editor"
|
||||
settingsImportedAt?: number
|
||||
historyPreviewCollapsed?: boolean
|
||||
taskTitlesEnabled?: boolean
|
||||
|
||||
cloudUserInfo: CloudUserInfo | null
|
||||
cloudIsAuthenticated: boolean
|
||||
|
|
|
|||
|
|
@ -2003,6 +2003,7 @@ export class ClineProvider
|
|||
historyPreviewCollapsed,
|
||||
reasoningBlockCollapsed,
|
||||
enterBehavior,
|
||||
taskTitlesEnabled,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated,
|
||||
sharingEnabled,
|
||||
|
|
@ -2093,6 +2094,7 @@ export class ClineProvider
|
|||
taskHistory: (taskHistory || [])
|
||||
.filter((item: HistoryItem) => item.ts && item.task)
|
||||
.sort((a: HistoryItem, b: HistoryItem) => b.ts - a.ts),
|
||||
taskTitlesEnabled: taskTitlesEnabled ?? false,
|
||||
soundEnabled: soundEnabled ?? false,
|
||||
ttsEnabled: ttsEnabled ?? false,
|
||||
ttsSpeed: ttsSpeed ?? 1.0,
|
||||
|
|
@ -2409,6 +2411,7 @@ export class ClineProvider
|
|||
historyPreviewCollapsed: stateValues.historyPreviewCollapsed ?? false,
|
||||
reasoningBlockCollapsed: stateValues.reasoningBlockCollapsed ?? true,
|
||||
enterBehavior: stateValues.enterBehavior ?? "send",
|
||||
taskTitlesEnabled: stateValues.taskTitlesEnabled ?? false,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated,
|
||||
sharingEnabled,
|
||||
|
|
|
|||
|
|
@ -1668,7 +1668,6 @@ export const webviewMessageHandler = async (
|
|||
await updateGlobalState("hasOpenedModeSelector", message.bool ?? true)
|
||||
await provider.postStateToWebview()
|
||||
break
|
||||
|
||||
case "toggleApiConfigPin":
|
||||
if (message.text) {
|
||||
const currentPinned = getGlobalState("pinnedApiConfigs") ?? {}
|
||||
|
|
|
|||
|
|
@ -376,7 +376,9 @@ const TaskHeader = ({
|
|||
<span className="font-bold">{t("chat:task.title")}</span>
|
||||
{renderTitleAction()}
|
||||
</div>
|
||||
{expandedTitleContent ? <div className="min-w-0">{expandedTitleContent}</div> : null}
|
||||
{expandedTitleContent ? (
|
||||
<div className="min-w-0">{expandedTitleContent}</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ let mockExtensionState: {
|
|||
apiConfiguration: ProviderSettings
|
||||
currentTaskItem: { id: string } | null
|
||||
clineMessages: any[]
|
||||
taskTitlesEnabled: boolean
|
||||
} = {
|
||||
apiConfiguration: {
|
||||
apiProvider: "anthropic",
|
||||
|
|
@ -57,6 +58,7 @@ let mockExtensionState: {
|
|||
} as ProviderSettings,
|
||||
currentTaskItem: { id: "test-task-id" },
|
||||
clineMessages: [],
|
||||
taskTitlesEnabled: true,
|
||||
}
|
||||
|
||||
// Mock the ExtensionStateContext
|
||||
|
|
@ -111,6 +113,7 @@ describe("TaskHeader", () => {
|
|||
} as ProviderSettings,
|
||||
currentTaskItem: { id: "test-task-id" },
|
||||
clineMessages: [],
|
||||
taskTitlesEnabled: true,
|
||||
}
|
||||
})
|
||||
const defaultProps: TaskHeaderProps = {
|
||||
|
|
@ -221,6 +224,14 @@ describe("TaskHeader", () => {
|
|||
})
|
||||
})
|
||||
|
||||
it("hides title controls when task titles are disabled", () => {
|
||||
mockExtensionState.taskTitlesEnabled = false
|
||||
renderTaskHeader()
|
||||
|
||||
expect(screen.queryByTestId("task-title-edit-button")).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId("task-title-display")).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
describe("DismissibleUpsell behavior", () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
|
|
@ -233,6 +244,7 @@ describe("TaskHeader", () => {
|
|||
} as ProviderSettings,
|
||||
currentTaskItem: { id: "test-task-id" },
|
||||
clineMessages: [],
|
||||
taskTitlesEnabled: true,
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import type { HistoryItem } from "@roo-code/types"
|
|||
import { vscode } from "@/utils/vscode"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
|
||||
import TaskItemFooter from "./TaskItemFooter"
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ const TaskItem = ({
|
|||
onDelete,
|
||||
className,
|
||||
}: TaskItemProps) => {
|
||||
const { taskTitlesEnabled = false } = useExtensionState()
|
||||
const handleClick = () => {
|
||||
if (isSelectionMode && onToggleSelection) {
|
||||
onToggleSelection(item.id, !isSelected)
|
||||
|
|
@ -42,6 +44,9 @@ const TaskItem = ({
|
|||
}
|
||||
|
||||
const isCompact = variant === "compact"
|
||||
const showTitle = taskTitlesEnabled && Boolean(item.title?.trim())
|
||||
const displayHighlight = showTitle && item.titleHighlight ? item.titleHighlight : item.highlight
|
||||
const displayText = showTitle && item.title ? item.title : item.task
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -70,37 +75,24 @@ const TaskItem = ({
|
|||
)}
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
{(item.title || item.titleHighlight) &&
|
||||
(item.titleHighlight ? (
|
||||
<div
|
||||
className={cn("text-vscode-foreground font-semibold truncate mb-1", {
|
||||
"text-base": !isCompact,
|
||||
"text-sm": isCompact,
|
||||
})}
|
||||
data-testid="task-item-title"
|
||||
dangerouslySetInnerHTML={{ __html: item.titleHighlight }}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={cn("text-vscode-foreground font-semibold truncate mb-1", {
|
||||
"text-base": !isCompact,
|
||||
"text-sm": isCompact,
|
||||
})}
|
||||
data-testid="task-item-title">
|
||||
{item.title}
|
||||
</div>
|
||||
))}
|
||||
<div
|
||||
className={cn(
|
||||
"overflow-hidden whitespace-pre-wrap font-light text-vscode-foreground text-ellipsis line-clamp-3",
|
||||
{
|
||||
"text-base": !isCompact,
|
||||
"text-sm": isCompact,
|
||||
},
|
||||
!isCompact && isSelectionMode ? "mb-1" : "",
|
||||
)}
|
||||
data-testid="task-content"
|
||||
{...(item.highlight ? { dangerouslySetInnerHTML: { __html: item.highlight } } : {})}>
|
||||
{item.highlight ? undefined : item.task}
|
||||
data-testid="task-content">
|
||||
{displayHighlight ? (
|
||||
<span
|
||||
className={cn(showTitle && "font-semibold")}
|
||||
dangerouslySetInnerHTML={{ __html: displayHighlight }}
|
||||
/>
|
||||
) : (
|
||||
<span className={cn(showTitle && "font-semibold")}>{displayText}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<TaskItemFooter
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@ import { render, screen, fireEvent } from "@/utils/test-utils"
|
|||
import TaskItem from "../TaskItem"
|
||||
|
||||
vi.mock("@src/utils/vscode")
|
||||
const mockUseExtensionState = vi.hoisted(() => vi.fn(() => ({ taskTitlesEnabled: true })))
|
||||
vi.mock("@/context/ExtensionStateContext", () => ({
|
||||
useExtensionState: mockUseExtensionState,
|
||||
}))
|
||||
vi.mock("@src/i18n/TranslationContext", () => ({
|
||||
useAppTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
|
|
@ -29,6 +33,7 @@ const mockTask = {
|
|||
describe("TaskItem", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockUseExtensionState.mockReturnValue({ taskTitlesEnabled: true })
|
||||
})
|
||||
|
||||
it("renders task information", () => {
|
||||
|
|
@ -80,7 +85,7 @@ describe("TaskItem", () => {
|
|||
expect(screen.getByTestId("export")).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it("renders title above task content when provided", () => {
|
||||
it("renders title instead of task text when provided", () => {
|
||||
render(
|
||||
<TaskItem
|
||||
item={{ ...mockTask, title: "Important task" }}
|
||||
|
|
@ -91,8 +96,28 @@ describe("TaskItem", () => {
|
|||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByTestId("task-item-title")).toHaveTextContent("Important task")
|
||||
expect(screen.getByTestId("task-content")).toHaveTextContent("Test task")
|
||||
const content = screen.getByTestId("task-content")
|
||||
expect(content).toHaveTextContent("Important task")
|
||||
expect(content).not.toHaveTextContent("Test task")
|
||||
expect(content.querySelector("span")?.className).toContain("font-semibold")
|
||||
})
|
||||
|
||||
it("falls back to task text when feature disabled", () => {
|
||||
mockUseExtensionState.mockReturnValue({ taskTitlesEnabled: false })
|
||||
render(
|
||||
<TaskItem
|
||||
item={{ ...mockTask, title: "Hidden title" }}
|
||||
variant="full"
|
||||
isSelected={false}
|
||||
onToggleSelection={vi.fn()}
|
||||
isSelectionMode={false}
|
||||
/>,
|
||||
)
|
||||
|
||||
const content = screen.getByTestId("task-content")
|
||||
expect(content).toHaveTextContent("Test task")
|
||||
expect(content).not.toHaveTextContent("Hidden title")
|
||||
expect(content.querySelector("span")?.className || "").not.toContain("font-semibold")
|
||||
})
|
||||
|
||||
it("displays time ago information", () => {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ describe("useTaskSearch", () => {
|
|||
mockUseExtensionState.mockReturnValue({
|
||||
taskHistory: mockTaskHistory,
|
||||
cwd: "/workspace/project1",
|
||||
taskTitlesEnabled: true,
|
||||
} as any)
|
||||
})
|
||||
|
||||
|
|
@ -169,6 +170,23 @@ describe("useTaskSearch", () => {
|
|||
expect((result.current.tasks[0] as any).titleHighlight).toBe("<mark>Build component</mark>")
|
||||
})
|
||||
|
||||
it("ignores task titles in search when the feature is disabled", () => {
|
||||
mockUseExtensionState.mockReturnValue({
|
||||
taskHistory: mockTaskHistory,
|
||||
cwd: "/workspace/project1",
|
||||
taskTitlesEnabled: false,
|
||||
} as any)
|
||||
|
||||
const { result } = renderHook(() => useTaskSearch())
|
||||
|
||||
act(() => {
|
||||
result.current.setShowAllWorkspaces(true)
|
||||
result.current.setSearchQuery("build")
|
||||
})
|
||||
|
||||
expect(result.current.tasks).toHaveLength(0)
|
||||
})
|
||||
|
||||
it("automatically switches to mostRelevant when searching", () => {
|
||||
const { result } = renderHook(() => useTaskSearch())
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { useExtensionState } from "@/context/ExtensionStateContext"
|
|||
type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRelevant"
|
||||
|
||||
export const useTaskSearch = () => {
|
||||
const { taskHistory, cwd } = useExtensionState()
|
||||
const { taskHistory, cwd, taskTitlesEnabled = false } = useExtensionState()
|
||||
const [searchQuery, setSearchQuery] = useState("")
|
||||
const [sortOption, setSortOption] = useState<SortOption>("newest")
|
||||
const [lastNonRelevantSort, setLastNonRelevantSort] = useState<SortOption | null>("newest")
|
||||
|
|
@ -33,9 +33,9 @@ export const useTaskSearch = () => {
|
|||
|
||||
const fzf = useMemo(() => {
|
||||
return new Fzf(presentableTasks, {
|
||||
selector: (item) => (item.title ? `${item.title} ${item.task}` : item.task),
|
||||
selector: (item) => (taskTitlesEnabled && item.title ? `${item.title} ${item.task}` : item.task),
|
||||
})
|
||||
}, [presentableTasks])
|
||||
}, [presentableTasks, taskTitlesEnabled])
|
||||
|
||||
const tasks = useMemo(() => {
|
||||
let results = presentableTasks
|
||||
|
|
@ -44,11 +44,14 @@ export const useTaskSearch = () => {
|
|||
const searchResults = fzf.find(searchQuery)
|
||||
results = searchResults.map((result) => {
|
||||
const positions = Array.from(result.positions)
|
||||
const titleLength = result.item.title ? result.item.title.length : 0
|
||||
const separatorLength = titleLength > 0 ? 1 : 0
|
||||
const taskOffset = titleLength + separatorLength
|
||||
const titlePositions = titleLength > 0 ? positions.filter((p) => p < titleLength) : []
|
||||
const taskPositions = positions.filter((p) => p >= taskOffset).map((p) => p - taskOffset)
|
||||
const includeTitles = taskTitlesEnabled && !!result.item.title
|
||||
const titleLength = includeTitles ? result.item.title!.length : 0
|
||||
const separatorLength = includeTitles ? 1 : 0
|
||||
const taskOffset = includeTitles ? titleLength + separatorLength : 0
|
||||
const titlePositions = includeTitles ? positions.filter((p) => p < titleLength) : []
|
||||
const taskPositions = includeTitles
|
||||
? positions.filter((p) => p >= taskOffset).map((p) => p - taskOffset)
|
||||
: positions
|
||||
|
||||
const titleHighlight =
|
||||
titlePositions.length > 0 && result.item.title
|
||||
|
|
@ -86,7 +89,7 @@ export const useTaskSearch = () => {
|
|||
return (b.ts || 0) - (a.ts || 0)
|
||||
}
|
||||
})
|
||||
}, [presentableTasks, searchQuery, fzf, sortOption])
|
||||
}, [presentableTasks, searchQuery, fzf, sortOption, taskTitlesEnabled])
|
||||
|
||||
return {
|
||||
tasks,
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
includeCurrentTime,
|
||||
includeCurrentCost,
|
||||
maxGitStatusFiles,
|
||||
taskTitlesEnabled,
|
||||
} = cachedState
|
||||
|
||||
const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration])
|
||||
|
|
@ -423,6 +424,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
condensingApiConfigId: condensingApiConfigId || "",
|
||||
includeTaskHistoryInEnhance: includeTaskHistoryInEnhance ?? true,
|
||||
reasoningBlockCollapsed: reasoningBlockCollapsed ?? true,
|
||||
taskTitlesEnabled: taskTitlesEnabled ?? false,
|
||||
enterBehavior: enterBehavior ?? "send",
|
||||
includeCurrentTime: includeCurrentTime ?? true,
|
||||
includeCurrentCost: includeCurrentCost ?? true,
|
||||
|
|
@ -910,6 +912,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
{/* UI Section */}
|
||||
{renderTab === "ui" && (
|
||||
<UISettings
|
||||
taskTitlesEnabled={taskTitlesEnabled ?? false}
|
||||
reasoningBlockCollapsed={reasoningBlockCollapsed ?? true}
|
||||
enterBehavior={enterBehavior ?? "send"}
|
||||
setCachedStateField={setCachedStateField}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,14 @@ import { SearchableSetting } from "./SearchableSetting"
|
|||
import { ExtensionStateContextType } from "@/context/ExtensionStateContext"
|
||||
|
||||
interface UISettingsProps extends HTMLAttributes<HTMLDivElement> {
|
||||
taskTitlesEnabled: boolean
|
||||
reasoningBlockCollapsed: boolean
|
||||
enterBehavior: "send" | "newline"
|
||||
setCachedStateField: SetCachedStateField<keyof ExtensionStateContextType>
|
||||
}
|
||||
|
||||
export const UISettings = ({
|
||||
taskTitlesEnabled,
|
||||
reasoningBlockCollapsed,
|
||||
enterBehavior,
|
||||
setCachedStateField,
|
||||
|
|
@ -28,6 +30,12 @@ export const UISettings = ({
|
|||
const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0
|
||||
return isMac ? "⌘" : "Ctrl"
|
||||
}, [])
|
||||
const handleTaskTitlesEnabledChange = (value: boolean) => {
|
||||
setCachedStateField("taskTitlesEnabled", value)
|
||||
telemetryClient.capture("ui_settings_task_titles_enabled_changed", {
|
||||
enabled: value,
|
||||
})
|
||||
}
|
||||
|
||||
const handleReasoningBlockCollapsedChange = (value: boolean) => {
|
||||
setCachedStateField("reasoningBlockCollapsed", value)
|
||||
|
|
@ -54,6 +62,18 @@ export const UISettings = ({
|
|||
|
||||
<Section>
|
||||
<div className="space-y-6">
|
||||
<div className="flex flex-col gap-1">
|
||||
<VSCodeCheckbox
|
||||
checked={taskTitlesEnabled}
|
||||
onChange={(e: any) => handleTaskTitlesEnabledChange(e.target.checked)}
|
||||
data-testid="enable-task-titles-checkbox">
|
||||
<span className="font-medium">{t("settings:ui.taskTitles.label")}</span>
|
||||
</VSCodeCheckbox>
|
||||
<div className="text-vscode-descriptionForeground text-sm ml-5 mt-1">
|
||||
{t("settings:ui.taskTitles.description")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Collapse Thinking Messages Setting */}
|
||||
<SearchableSetting
|
||||
settingId="ui-collapse-thinking"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { UISettings } from "../UISettings"
|
|||
|
||||
describe("UISettings", () => {
|
||||
const defaultProps = {
|
||||
taskTitlesEnabled: false,
|
||||
reasoningBlockCollapsed: false,
|
||||
enterBehavior: "send" as const,
|
||||
setCachedStateField: vi.fn(),
|
||||
|
|
@ -15,6 +16,12 @@ describe("UISettings", () => {
|
|||
expect(checkbox).toBeTruthy()
|
||||
})
|
||||
|
||||
it("renders the task titles checkbox", () => {
|
||||
const { getByTestId } = render(<UISettings {...defaultProps} />)
|
||||
const checkbox = getByTestId("enable-task-titles-checkbox")
|
||||
expect(checkbox).toBeTruthy()
|
||||
})
|
||||
|
||||
it("displays the correct initial state", () => {
|
||||
const { getByTestId } = render(<UISettings {...defaultProps} reasoningBlockCollapsed={true} />)
|
||||
const checkbox = getByTestId("collapse-thinking-checkbox") as HTMLInputElement
|
||||
|
|
@ -41,4 +48,18 @@ describe("UISettings", () => {
|
|||
rerender(<UISettings {...defaultProps} reasoningBlockCollapsed={true} />)
|
||||
expect(checkbox.checked).toBe(true)
|
||||
})
|
||||
|
||||
it("calls setCachedStateField when task titles checkbox is toggled", async () => {
|
||||
const setCachedStateField = vi.fn()
|
||||
const { getByTestId } = render(
|
||||
<UISettings {...defaultProps} setCachedStateField={setCachedStateField} taskTitlesEnabled={false} />,
|
||||
)
|
||||
|
||||
const checkbox = getByTestId("enable-task-titles-checkbox")
|
||||
fireEvent.click(checkbox)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(setCachedStateField).toHaveBeenCalledWith("taskTitlesEnabled", true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
togglePinnedApiConfig: (configName: string) => void
|
||||
terminalCompressProgressBar?: boolean
|
||||
setTerminalCompressProgressBar: (value: boolean) => void
|
||||
taskTitlesEnabled?: boolean
|
||||
setTaskTitlesEnabled: (value: boolean) => void
|
||||
setHistoryPreviewCollapsed: (value: boolean) => void
|
||||
setReasoningBlockCollapsed: (value: boolean) => void
|
||||
enterBehavior?: "send" | "newline"
|
||||
|
|
@ -253,6 +255,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
historyPreviewCollapsed: false, // Initialize the new state (default to expanded)
|
||||
reasoningBlockCollapsed: true, // Default to collapsed
|
||||
enterBehavior: "send", // Default: Enter sends, Shift+Enter creates newline
|
||||
taskTitlesEnabled: false,
|
||||
cloudUserInfo: null,
|
||||
cloudIsAuthenticated: false,
|
||||
cloudOrganizations: [],
|
||||
|
|
@ -454,6 +457,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
const contextValue: ExtensionStateContextType = {
|
||||
...state,
|
||||
reasoningBlockCollapsed: state.reasoningBlockCollapsed ?? true,
|
||||
taskTitlesEnabled: state.taskTitlesEnabled ?? false,
|
||||
didHydrateState,
|
||||
showWelcome,
|
||||
theme,
|
||||
|
|
@ -574,6 +578,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
setState((prevState) => ({ ...prevState, reasoningBlockCollapsed: value })),
|
||||
enterBehavior: state.enterBehavior ?? "send",
|
||||
setEnterBehavior: (value) => setState((prevState) => ({ ...prevState, enterBehavior: value })),
|
||||
setTaskTitlesEnabled: (value) => setState((prevState) => ({ ...prevState, taskTitlesEnabled: value })),
|
||||
setHasOpenedModeSelector: (value) => setState((prevState) => ({ ...prevState, hasOpenedModeSelector: value })),
|
||||
setAutoCondenseContext: (value) => setState((prevState) => ({ ...prevState, autoCondenseContext: value })),
|
||||
setAutoCondenseContextPercent: (value) =>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@
|
|||
"description": "Manage your slash commands to quickly execute custom workflows and actions. <DocsLink>Learn more</DocsLink>"
|
||||
},
|
||||
"ui": {
|
||||
"taskTitles": {
|
||||
"label": "Enable editable task titles",
|
||||
"description": "Show and edit custom titles for tasks in chat and history instead of only the original task text"
|
||||
},
|
||||
"collapseThinking": {
|
||||
"label": "Collapse Thinking messages by default",
|
||||
"description": "When enabled, thinking blocks will be collapsed by default until you interact with them"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue