-
Notifications
You must be signed in to change notification settings - Fork 35.5k
wip terminal inline chat #270821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
wip terminal inline chat #270821
Conversation
import type { ITerminalInstance } from '../../../../terminal/browser/terminal.js'; | ||
import { TerminalInstance, TerminalInstanceColorProvider } from '../../../../terminal/browser/terminalInstance.js'; | ||
import { XtermTerminal } from '../../../../terminal/browser/xterm/xtermTerminal.js'; | ||
// TODO@meganrogge fix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To do: fix somehow, this was also in initial PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements terminal inline chat functionality by adding the ability to track terminal execution strategies and display terminal output inline within chat responses. The implementation allows chat responses to show live terminal output by creating dedicated terminal instances that mirror the execution happening in the background.
Key changes:
- Enhanced terminal execute strategies with marker tracking and update events
- Added terminal output display capabilities to chat terminal tool progress parts
- Implemented terminal instance tracking and content synchronization
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 11 comments.
Show a summary per file
File | Description |
---|---|
runInTerminalTool.ts | Adds execution tracking with UUID generation and strategy association |
strategyHelpers.ts | Modifies marker disposal to prevent cleanup for persistent UI access |
richExecuteStrategy.ts | Extends Disposable and adds marker/update event properties |
noneExecuteStrategy.ts | Extends Disposable and adds marker/update event properties |
executeStrategy.ts | Defines new interface properties for markers and update events |
basicExecuteStrategy.ts | Extends Disposable and adds marker/update event properties |
xtermTerminal.ts | Adds VT sequence serialization method for terminal content extraction |
terminalInstance.ts | Updates color provider constructor to support flexible location types |
terminal.ts | Adds interface method for VT range serialization |
chatToolInvocationPart.ts | Reorders import statements |
chatTerminalToolProgressPart.ts | Major enhancement adding terminal instance tracking and live output display |
// TODO@meganrogge !!! does this cause disposables to be leaked? | ||
// Don't clear the start marker on disposal - we want it to persist | ||
// so terminal UI parts can still access it | ||
console.log('strategy disposed but keeping start marker'); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace console.log with proper logging using the ITerminalLogService that's available in the execute strategy classes.
console.log('strategy disposed but keeping start marker'); | |
log?.('strategy disposed but keeping start marker'); |
Copilot uses AI. Check for mistakes.
} | ||
} else if (!this.xterm) { | ||
// Missing required services, can't create terminal yet | ||
console.log(`Can't create terminal for ${this.externalInstanceId} yet - missing required services`); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace console.log statements with proper logging. Consider using ILogService or another appropriate logging mechanism available through dependency injection.
Copilot uses AI. Check for mistakes.
console.log(`Start marker already exists for ${this.externalInstanceId} - using for initial data`); | ||
await this.updateTerminalContent(instance, executeStrategy, executeStrategy.startMarker); | ||
} catch (e) { | ||
console.error(`Error getting initial terminal data for ${this.externalInstanceId}:`, e); | ||
} | ||
} else { | ||
console.log(`No start marker available yet for ${this.externalInstanceId} - waiting for marker creation event. Has strategy: ${!!executeStrategy}`); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace all console.log/console.error statements with proper logging using an injected logging service. This will provide better debugging capabilities and follow VS Code's logging patterns.
Copilot uses AI. Check for mistakes.
): Promise<void> { | ||
const latestPartId = ChatTerminalToolProgressPart.latestPartPerInstance.get(this.instanceType!); | ||
if (latestPartId !== this.externalInstanceId) { | ||
console.log(`Skipping update for ${this.externalInstanceId} as ${latestPartId} is the latest`); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace all console.log/console.error statements with proper logging using an injected logging service. This will provide better debugging capabilities and follow VS Code's logging patterns.
Copilot uses AI. Check for mistakes.
// Try persistent marker first | ||
if (this.persistentStartMarker) { | ||
startMarker = this.persistentStartMarker; | ||
console.log(`Using persistent start marker for ${this.externalInstanceId}`); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace all console.log/console.error statements with proper logging using an injected logging service. This will provide better debugging capabilities and follow VS Code's logging patterns.
Copilot uses AI. Check for mistakes.
...ch/contrib/chat/browser/chatContentParts/toolInvocationParts/chatTerminalToolProgressPart.ts
Outdated
Show resolved
Hide resolved
...ch/contrib/chat/browser/chatContentParts/toolInvocationParts/chatTerminalToolProgressPart.ts
Outdated
Show resolved
Hide resolved
...ch/contrib/chat/browser/chatContentParts/toolInvocationParts/chatTerminalToolProgressPart.ts
Outdated
Show resolved
Hide resolved
// eslint-disable-next-line local/code-import-patterns | ||
import type { ITerminalExecuteStrategy } from '../../../../terminalContrib/chatAgentTools/browser/executeStrategy/executeStrategy.js'; |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The eslint-disable comment indicates an import pattern violation that should be addressed. Consider restructuring the imports to follow the established patterns or moving the shared types to a more appropriate location.
// eslint-disable-next-line local/code-import-patterns | |
import type { ITerminalExecuteStrategy } from '../../../../terminalContrib/chatAgentTools/browser/executeStrategy/executeStrategy.js'; | |
import type { ITerminalExecuteStrategy } from '../../../../terminalContrib/chatAgentTools/common/executeStrategyTypes.js'; |
Copilot uses AI. Check for mistakes.
// const icon = !toolInvocation.isConfirmed ? | ||
// Codicon.error : | ||
// toolInvocation.isComplete ? | ||
// Codicon.check : ThemeIcon.modify(Codicon.loading, 'spin'); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove commented-out code. If this icon logic is needed for future implementation, consider adding a proper TODO comment or implement it immediately.
// const icon = !toolInvocation.isConfirmed ? | |
// Codicon.error : | |
// toolInvocation.isComplete ? | |
// Codicon.check : ThemeIcon.modify(Codicon.loading, 'spin'); | |
// TODO: Implement icon logic for toolInvocation status if needed (see previous commented-out code). |
Copilot uses AI. Check for mistakes.
5b2a5e8
to
0e74037
Compare
// TODO@meganrogge !!! does this cause disposables to be leaked? | ||
// Don't clear the start marker on disposal - we want it to persist | ||
// so terminal UI parts can still access it | ||
console.log('strategy disposed but keeping start marker'); | ||
// Don't fire undefined marker event - keep the last valid marker | ||
})); | ||
store.add(startMarker); | ||
// We don't register startMarker with the store to prevent it from being auto-disposed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
todo: fix somehow, with this clearing code, it doesn't work.
But the peristentMarker thing should make this ok 🤔 . maybe timing issue
// Map from real terminal instance IDs to chat terminal parts | ||
private static readonly instanceToPartMap = new Map<string, Set<ChatTerminalToolProgressPart>>(); | ||
|
||
// Track the latest part for each terminal instance type (command, output display, etc) | ||
private static readonly latestPartPerInstance = new Map<string, string>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This thing was really hacky just to get something working, we need to come up with a proper way of transferring the terminal over to the tool. Since we don't necessarily know the instance to be used before this object is constructed it makes things more complicated.
Perhaps a new ITerminalChatService
who's job it is initially purely to track these things and make sure they're serialized correctly (so things don't break on reload). Might be worth chatting about this in a sync together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, and this file is getting way too big, needs separation.
Here are some notes I made:
// Chat Session
// ├── Chat Request → Xterm → Instance (start marker → end marker)
// ├── Chat Request → Xterm → Instance (start marker → end marker)
// └── Chat Request → Xterm → Instance (start marker → end marker)
// ...
// Notes:
// - Each Instance should be headless, hidden, and per Chat Request?
// - Should allow opening terminals from the chat-embedded one?
interface ChatEmbeddedTerminalService {
map: Map<ChatSessionId, Xterm[]>;
createTerminal(): Xterm;
serialize(): string;
deserialize(data: string): void;
Branched from #261503 because there were many merge conflicts and I was nervous to break something
Current status:
To do: