mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 22:03:45 +00:00
feat(coding-agent): add /resume command to switch sessions mid-conversation
- Opens interactive session selector - Properly aborts in-flight agent turns before switching - Restores model and thinking level from resumed session - Clears UI state (queued messages, pending tools, etc.) closes #117
This commit is contained in:
parent
30f63bcaf6
commit
4bd52cf3ed
1 changed files with 61 additions and 19 deletions
|
|
@ -1489,26 +1489,9 @@ export class TuiRenderer {
|
|||
// Create session selector
|
||||
this.sessionSelector = new SessionSelectorComponent(
|
||||
this.sessionManager,
|
||||
(sessionPath) => {
|
||||
// Set the selected session as active
|
||||
this.sessionManager.setSessionFile(sessionPath);
|
||||
|
||||
// Reload the session
|
||||
const loaded = loadSessionFromEntries(this.sessionManager.loadEntries());
|
||||
this.agent.replaceMessages(loaded.messages);
|
||||
|
||||
// Clear and re-render the chat
|
||||
this.chatContainer.clear();
|
||||
this.isFirstUserMessage = true;
|
||||
this.renderInitialMessages(this.agent.state);
|
||||
|
||||
// Show confirmation message
|
||||
this.chatContainer.addChild(new Spacer(1));
|
||||
this.chatContainer.addChild(new Text(theme.fg("dim", "Resumed session"), 1, 0));
|
||||
|
||||
// Hide selector and show editor again
|
||||
async (sessionPath) => {
|
||||
this.hideSessionSelector();
|
||||
this.ui.requestRender();
|
||||
await this.handleResumeSession(sessionPath);
|
||||
},
|
||||
() => {
|
||||
// Just hide the selector
|
||||
|
|
@ -1524,6 +1507,65 @@ export class TuiRenderer {
|
|||
this.ui.requestRender();
|
||||
}
|
||||
|
||||
private async handleResumeSession(sessionPath: string): Promise<void> {
|
||||
// Unsubscribe first to prevent processing events during transition
|
||||
this.unsubscribe?.();
|
||||
|
||||
// Abort and wait for completion
|
||||
this.agent.abort();
|
||||
await this.agent.waitForIdle();
|
||||
|
||||
// Stop loading animation
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = null;
|
||||
}
|
||||
this.statusContainer.clear();
|
||||
|
||||
// Clear UI state
|
||||
this.queuedMessages = [];
|
||||
this.pendingMessagesContainer.clear();
|
||||
this.streamingComponent = null;
|
||||
this.pendingTools.clear();
|
||||
|
||||
// Set the selected session as active
|
||||
this.sessionManager.setSessionFile(sessionPath);
|
||||
|
||||
// Reload the session
|
||||
const loaded = loadSessionFromEntries(this.sessionManager.loadEntries());
|
||||
this.agent.replaceMessages(loaded.messages);
|
||||
|
||||
// Restore model if saved in session
|
||||
const savedModel = this.sessionManager.loadModel();
|
||||
if (savedModel) {
|
||||
const availableModels = (await getAvailableModels()).models;
|
||||
const match = availableModels.find((m) => m.provider === savedModel.provider && m.id === savedModel.modelId);
|
||||
if (match) {
|
||||
this.agent.setModel(match);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore thinking level if saved in session
|
||||
const savedThinking = this.sessionManager.loadThinkingLevel();
|
||||
if (savedThinking) {
|
||||
this.agent.setThinkingLevel(savedThinking as ThinkingLevel);
|
||||
}
|
||||
|
||||
// Resubscribe to agent
|
||||
this.subscribeToAgent();
|
||||
|
||||
// Clear and re-render the chat
|
||||
this.chatContainer.clear();
|
||||
this.isFirstUserMessage = true;
|
||||
this.renderInitialMessages(this.agent.state);
|
||||
|
||||
// Show confirmation message
|
||||
this.chatContainer.addChild(new Spacer(1));
|
||||
this.chatContainer.addChild(new Text(theme.fg("dim", "Resumed session"), 1, 0));
|
||||
|
||||
this.ui.requestRender();
|
||||
}
|
||||
|
||||
private hideSessionSelector(): void {
|
||||
// Replace selector with editor in the container
|
||||
this.editorContainer.clear();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue