Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions src/integrations/terminal/TerminalManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,6 @@ Interestingly, some environments like Cursor enable these APIs even without the
This approach allows us to leverage advanced features when available while ensuring broad compatibility.
*/
declare module "vscode" {
// https://github.com/microsoft/vscode/blob/f0417069c62e20f3667506f4b7e53ca0004b4e3e/src/vscode-dts/vscode.d.ts#L7442
interface Terminal {
shellIntegration?: {
cwd?: vscode.Uri
executeCommand?: (command: string) => {
read: () => AsyncIterable<string>
}
}
}
// https://github.com/microsoft/vscode/blob/f0417069c62e20f3667506f4b7e53ca0004b4e3e/src/vscode-dts/vscode.d.ts#L10794
interface Window {
onDidStartTerminalShellExecution?: (
Expand All @@ -89,6 +80,16 @@ declare module "vscode" {
}
}

// Extend the Terminal type to include our custom properties
type ExtendedTerminal = vscode.Terminal & {
shellIntegration?: {
cwd?: vscode.Uri
executeCommand?: (command: string) => {
read: () => AsyncIterable<string>
}
}
}

export class TerminalManager {
private terminalIds: Set<number> = new Set()
private processes: Map<number, TerminalProcess> = new Map()
Expand Down Expand Up @@ -139,16 +140,17 @@ export class TerminalManager {
})

// if shell integration is already active, run the command immediately
if (terminalInfo.terminal.shellIntegration) {
const terminal = terminalInfo.terminal as ExtendedTerminal
if (terminal.shellIntegration) {
process.waitForShellIntegration = false
process.run(terminalInfo.terminal, command)
process.run(terminal, command)
} else {
// docs recommend waiting 3s for shell integration to activate
pWaitFor(() => terminalInfo.terminal.shellIntegration !== undefined, { timeout: 4000 }).finally(() => {
pWaitFor(() => (terminalInfo.terminal as ExtendedTerminal).shellIntegration !== undefined, { timeout: 4000 }).finally(() => {
const existingProcess = this.processes.get(terminalInfo.id)
if (existingProcess && existingProcess.waitForShellIntegration) {
existingProcess.waitForShellIntegration = false
existingProcess.run(terminalInfo.terminal, command)
existingProcess.run(terminal, command)
}
})
}
Expand All @@ -162,7 +164,8 @@ export class TerminalManager {
if (t.busy) {
return false
}
const terminalCwd = t.terminal.shellIntegration?.cwd // one of cline's commands could have changed the cwd of the terminal
const terminal = t.terminal as ExtendedTerminal
const terminalCwd = terminal.shellIntegration?.cwd // one of cline's commands could have changed the cwd of the terminal
if (!terminalCwd) {
return false
}
Expand Down