mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-21 10:00:39 +00:00
Merge branch 'feat/resume-slash-command'
This commit is contained in:
commit
94d6c6704b
3 changed files with 117 additions and 0 deletions
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- **`/resume` Command**: Switch to a different session mid-conversation. Opens an interactive selector showing all available sessions. Equivalent to the `--resume` CLI flag but can be used without restarting the agent. ([#117](https://github.com/badlogic/pi-mono/pull/117) by [@hewliyang](https://github.com/hewliyang))
|
||||||
- **`authHeader` option in models.json**: Custom providers can set `"authHeader": true` to automatically add `Authorization: Bearer <apiKey>` header. Useful for providers that require explicit auth headers. ([#81](https://github.com/badlogic/pi-mono/issues/81))
|
- **`authHeader` option in models.json**: Custom providers can set `"authHeader": true` to automatically add `Authorization: Bearer <apiKey>` header. Useful for providers that require explicit auth headers. ([#81](https://github.com/badlogic/pi-mono/issues/81))
|
||||||
- **`--append-system-prompt` Flag**: Append additional text or file contents to the system prompt. Supports both inline text and file paths. Complements `--system-prompt` for layering custom instructions without replacing the base system prompt. ([#114](https://github.com/badlogic/pi-mono/pull/114) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- **`--append-system-prompt` Flag**: Append additional text or file contents to the system prompt. Supports both inline text and file paths. Complements `--system-prompt` for layering custom instructions without replacing the base system prompt. ([#114](https://github.com/badlogic/pi-mono/pull/114) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
- **Thinking Block Toggle**: Added `Ctrl+T` shortcut to toggle visibility of LLM thinking blocks. When toggled off, shows a static "Thinking..." label instead of full content. Useful for reducing visual clutter during long conversations. ([#113](https://github.com/badlogic/pi-mono/pull/113) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- **Thinking Block Toggle**: Added `Ctrl+T` shortcut to toggle visibility of LLM thinking blocks. When toggled off, shows a static "Thinking..." label instead of full content. Useful for reducing visual clutter during long conversations. ([#113](https://github.com/badlogic/pi-mono/pull/113) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
|
|
|
||||||
|
|
@ -502,6 +502,16 @@ This allows you to explore alternative conversation paths without losing your cu
|
||||||
/branch
|
/branch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### /resume
|
||||||
|
|
||||||
|
Switch to a different session. Opens an interactive selector showing all available sessions. Select a session to load it and continue where you left off.
|
||||||
|
|
||||||
|
This is equivalent to the `--resume` CLI flag but can be used mid-session.
|
||||||
|
|
||||||
|
```
|
||||||
|
/resume
|
||||||
|
```
|
||||||
|
|
||||||
### /login
|
### /login
|
||||||
|
|
||||||
Login with OAuth to use subscription-based models (Claude Pro/Max):
|
Login with OAuth to use subscription-based models (Claude Pro/Max):
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import { FooterComponent } from "./footer.js";
|
||||||
import { ModelSelectorComponent } from "./model-selector.js";
|
import { ModelSelectorComponent } from "./model-selector.js";
|
||||||
import { OAuthSelectorComponent } from "./oauth-selector.js";
|
import { OAuthSelectorComponent } from "./oauth-selector.js";
|
||||||
import { QueueModeSelectorComponent } from "./queue-mode-selector.js";
|
import { QueueModeSelectorComponent } from "./queue-mode-selector.js";
|
||||||
|
import { SessionSelectorComponent } from "./session-selector.js";
|
||||||
import { ThemeSelectorComponent } from "./theme-selector.js";
|
import { ThemeSelectorComponent } from "./theme-selector.js";
|
||||||
import { ThinkingSelectorComponent } from "./thinking-selector.js";
|
import { ThinkingSelectorComponent } from "./thinking-selector.js";
|
||||||
import { ToolExecutionComponent } from "./tool-execution.js";
|
import { ToolExecutionComponent } from "./tool-execution.js";
|
||||||
|
|
@ -95,6 +96,9 @@ export class TuiRenderer {
|
||||||
// User message selector (for branching)
|
// User message selector (for branching)
|
||||||
private userMessageSelector: UserMessageSelectorComponent | null = null;
|
private userMessageSelector: UserMessageSelectorComponent | null = null;
|
||||||
|
|
||||||
|
// Session selector (for resume)
|
||||||
|
private sessionSelector: SessionSelectorComponent | null = null;
|
||||||
|
|
||||||
// OAuth selector
|
// OAuth selector
|
||||||
private oauthSelector: any | null = null;
|
private oauthSelector: any | null = null;
|
||||||
|
|
||||||
|
|
@ -214,6 +218,11 @@ export class TuiRenderer {
|
||||||
description: "Toggle automatic context compaction",
|
description: "Toggle automatic context compaction",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resumeCommand: SlashCommand = {
|
||||||
|
name: "resume",
|
||||||
|
description: "Resume a different session",
|
||||||
|
};
|
||||||
|
|
||||||
// Load hide thinking block setting
|
// Load hide thinking block setting
|
||||||
this.hideThinkingBlock = settingsManager.getHideThinkingBlock();
|
this.hideThinkingBlock = settingsManager.getHideThinkingBlock();
|
||||||
|
|
||||||
|
|
@ -243,6 +252,7 @@ export class TuiRenderer {
|
||||||
clearCommand,
|
clearCommand,
|
||||||
compactCommand,
|
compactCommand,
|
||||||
autocompactCommand,
|
autocompactCommand,
|
||||||
|
resumeCommand,
|
||||||
...fileSlashCommands,
|
...fileSlashCommands,
|
||||||
],
|
],
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
|
|
@ -488,6 +498,13 @@ export class TuiRenderer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for /resume command
|
||||||
|
if (text === "/resume") {
|
||||||
|
this.showSessionSelector();
|
||||||
|
this.editor.setText("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for file-based slash commands
|
// Check for file-based slash commands
|
||||||
text = expandSlashCommand(text, this.fileCommands);
|
text = expandSlashCommand(text, this.fileCommands);
|
||||||
|
|
||||||
|
|
@ -1490,6 +1507,95 @@ export class TuiRenderer {
|
||||||
this.ui.setFocus(this.editor);
|
this.ui.setFocus(this.editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private showSessionSelector(): void {
|
||||||
|
// Create session selector
|
||||||
|
this.sessionSelector = new SessionSelectorComponent(
|
||||||
|
this.sessionManager,
|
||||||
|
async (sessionPath) => {
|
||||||
|
this.hideSessionSelector();
|
||||||
|
await this.handleResumeSession(sessionPath);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
// Just hide the selector
|
||||||
|
this.hideSessionSelector();
|
||||||
|
this.ui.requestRender();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Replace editor with selector
|
||||||
|
this.editorContainer.clear();
|
||||||
|
this.editorContainer.addChild(this.sessionSelector);
|
||||||
|
this.ui.setFocus(this.sessionSelector.getSessionList());
|
||||||
|
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();
|
||||||
|
this.editorContainer.addChild(this.editor);
|
||||||
|
this.sessionSelector = null;
|
||||||
|
this.ui.setFocus(this.editor);
|
||||||
|
}
|
||||||
|
|
||||||
private async showOAuthSelector(mode: "login" | "logout"): Promise<void> {
|
private async showOAuthSelector(mode: "login" | "logout"): Promise<void> {
|
||||||
// For logout mode, filter to only show logged-in providers
|
// For logout mode, filter to only show logged-in providers
|
||||||
let providersToShow: string[] = [];
|
let providersToShow: string[] = [];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue