Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | import { UpdateTerminalConnectionTimeoutResponse } from "@shared/proto/index.cline"
import { VSCodeCheckbox, VSCodeDropdown, VSCodeOption, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import React, { useState } from "react"
import { PlatformType } from "@/config/platform.config"
import { useExtensionState } from "@/context/ExtensionStateContext"
import { usePlatform } from "@/context/PlatformContext"
import { StateServiceClient } from "../../../services/grpc-client"
import Section from "../Section"
import TerminalOutputLineLimitSlider from "../TerminalOutputLineLimitSlider"
import { updateSetting } from "../utils/settingsHandlers"
interface TerminalSettingsSectionProps {
renderSectionHeader: (tabId: string) => JSX.Element | null
}
export const TerminalSettingsSection: React.FC<TerminalSettingsSectionProps> = ({ renderSectionHeader }) => {
const {
shellIntegrationTimeout,
terminalReuseEnabled,
defaultTerminalProfile,
availableTerminalProfiles,
vscodeTerminalExecutionMode,
} = useExtensionState()
const platformConfig = usePlatform()
const isVsCodePlatform = platformConfig.type === PlatformType.VSCODE
const [inputValue, setInputValue] = useState((shellIntegrationTimeout / 1000).toString())
const [inputError, setInputError] = useState<string | null>(null)
const handleTimeoutChange = (event: Event) => {
const target = event.target as HTMLInputElement
const value = target.value
setInputValue(value)
const seconds = parseFloat(value)
if (Number.isNaN(seconds) || seconds <= 0) {
setInputError("Please enter a positive number")
return
}
setInputError(null)
const timeoutMs = Math.round(seconds * 1000)
StateServiceClient.updateTerminalConnectionTimeout({ timeoutMs })
.then((response: UpdateTerminalConnectionTimeoutResponse) => {
const timeoutMs = response.timeoutMs
// Backend calls postStateToWebview(), so state will update via subscription
// Just sync the input value with the confirmed backend value
if (timeoutMs !== undefined) {
setInputValue((timeoutMs / 1000).toString())
}
})
.catch((error) => {
console.error("Failed to update terminal connection timeout:", error)
})
}
const handleInputBlur = () => {
if (inputError) {
setInputValue((shellIntegrationTimeout / 1000).toString())
setInputError(null)
}
}
const handleTerminalReuseChange = (event: Event) => {
const target = event.target as HTMLInputElement
const checked = target.checked
updateSetting("terminalReuseEnabled", checked)
}
const handleExecutionModeChange = (event: Event) => {
const target = event.target as HTMLSelectElement
const value = target.value === "backgroundExec" ? "backgroundExec" : "vscodeTerminal"
updateSetting("vscodeTerminalExecutionMode", value)
}
// Use any to avoid type conflicts between Event and FormEvent
const handleDefaultTerminalProfileChange = (event: any) => {
const target = event.target as HTMLSelectElement
const profileId = target.value
// Save immediately using the consolidated updateSettings approach
updateSetting("defaultTerminalProfile", profileId || "default")
}
const profilesToShow = availableTerminalProfiles
return (
<div>
{renderSectionHeader("terminal")}
<Section>
<div className="mb-5" id="terminal-settings-section">
<div className="mb-4">
<label className="font-medium block mb-1" htmlFor="default-terminal-profile">
Default Terminal Profile
</label>
<VSCodeDropdown
className="w-full"
id="default-terminal-profile"
onChange={handleDefaultTerminalProfileChange}
value={defaultTerminalProfile || "default"}>
{profilesToShow.map((profile) => (
<VSCodeOption key={profile.id} title={profile.description} value={profile.id}>
{profile.name}
</VSCodeOption>
))}
</VSCodeDropdown>
<p className="text-xs text-[var(--vscode-descriptionForeground)] mt-1">
Select the default terminal AI-Hydro will use. 'Default' uses your VSCode global setting.
</p>
</div>
<div className="mb-4">
<div className="mb-2">
<label className="font-medium block mb-1">Shell integration timeout (seconds)</label>
<div className="flex items-center">
<VSCodeTextField
className="w-full"
onBlur={handleInputBlur}
onChange={(event) => handleTimeoutChange(event as Event)}
placeholder="Enter timeout in seconds"
value={inputValue}
/>
</div>
{inputError && <div className="text-[var(--vscode-errorForeground)] text-xs mt-1">{inputError}</div>}
</div>
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
Set how long AI-Hydro waits for shell integration to activate before executing commands. Increase this
value if you experience terminal connection timeouts.
</p>
</div>
<div className="mb-4">
<div className="flex items-center mb-2">
<VSCodeCheckbox
checked={terminalReuseEnabled ?? true}
onChange={(event) => handleTerminalReuseChange(event as Event)}>
Enable aggressive terminal reuse
</VSCodeCheckbox>
</div>
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
When enabled, AI-Hydro will reuse existing terminal windows that aren't in the current working
directory. Disable this if you experience issues with task lockout after a terminal command.
</p>
</div>
{isVsCodePlatform && (
<div className="mb-4">
<label className="font-medium block mb-1" htmlFor="terminal-execution-mode">
Terminal Execution Mode
</label>
<VSCodeDropdown
className="w-full"
id="terminal-execution-mode"
onChange={(event) => handleExecutionModeChange(event as Event)}
value={vscodeTerminalExecutionMode ?? "vscodeTerminal"}>
<VSCodeOption value="vscodeTerminal">VS Code Terminal</VSCodeOption>
<VSCodeOption value="backgroundExec">Background Exec</VSCodeOption>
</VSCodeDropdown>
<p className="text-xs text-[var(--vscode-descriptionForeground)] mt-1">
Choose whether AI-Hydro runs commands in the VS Code terminal or a background process.
</p>
</div>
)}
<TerminalOutputLineLimitSlider />
<div className="mt-5 p-3 bg-[var(--vscode-textBlockQuote-background)] rounded border border-[var(--vscode-textBlockQuote-border)]">
<p className="text-[13px] m-0">
<strong>Having terminal issues?</strong> Check our{" "}
<a
className="text-[var(--vscode-textLink-foreground)] underline hover:no-underline"
href="https://github.com/AI-Hydro/AI-Hydro/issues"
rel="noopener noreferrer"
target="_blank">
Terminal Quick Fixes
</a>{" "}
or the{" "}
<a
className="text-[var(--vscode-textLink-foreground)] underline hover:no-underline"
href="https://github.com/AI-Hydro/AI-Hydro/issues"
rel="noopener noreferrer"
target="_blank">
Complete Troubleshooting Guide
</a>
.
</p>
</div>
</div>
</Section>
</div>
)
}
export default TerminalSettingsSection
|