mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 03:01:56 +00:00
feat(coding-agent): implement /tree command for session tree navigation
- Add TreeSelectorComponent with ASCII tree visualization - Add AgentSession.navigateTree() for switching branches - Add session_before_tree/session_tree hook events - Add SessionManager.resetLeaf() for navigating to root - Change leafId from string to string|null for consistency with parentId - Support optional branch summarization when switching - Update buildSessionContext() to handle null leafId - Add /tree to slash commands in interactive mode
This commit is contained in:
parent
256761e410
commit
4958271dd3
9 changed files with 893 additions and 443 deletions
|
|
@ -51,6 +51,7 @@ import { OAuthSelectorComponent } from "./components/oauth-selector.js";
|
|||
import { SessionSelectorComponent } from "./components/session-selector.js";
|
||||
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
||||
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
||||
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
||||
import { UserMessageComponent } from "./components/user-message.js";
|
||||
import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
|
||||
import { getAvailableThemes, getEditorTheme, getMarkdownTheme, onThemeChange, setTheme, theme } from "./theme/theme.js";
|
||||
|
|
@ -155,6 +156,7 @@ export class InteractiveMode {
|
|||
{ name: "changelog", description: "Show changelog entries" },
|
||||
{ name: "hotkeys", description: "Show all keyboard shortcuts" },
|
||||
{ name: "branch", description: "Create a new branch from a previous message" },
|
||||
{ name: "tree", description: "Navigate session tree (switch branches)" },
|
||||
{ name: "login", description: "Login with OAuth provider" },
|
||||
{ name: "logout", description: "Logout from OAuth provider" },
|
||||
{ name: "new", description: "Start a new session" },
|
||||
|
|
@ -679,6 +681,11 @@ export class InteractiveMode {
|
|||
this.editor.setText("");
|
||||
return;
|
||||
}
|
||||
if (text === "/tree") {
|
||||
this.showTreeSelector();
|
||||
this.editor.setText("");
|
||||
return;
|
||||
}
|
||||
if (text === "/login") {
|
||||
this.showOAuthSelector("login");
|
||||
this.editor.setText("");
|
||||
|
|
@ -1585,6 +1592,63 @@ export class InteractiveMode {
|
|||
});
|
||||
}
|
||||
|
||||
private showTreeSelector(): void {
|
||||
const tree = this.sessionManager.getTree();
|
||||
const currentLeafId = this.sessionManager.getLeafUuid();
|
||||
|
||||
if (tree.length === 0) {
|
||||
this.showStatus("No entries in session");
|
||||
return;
|
||||
}
|
||||
|
||||
this.showSelector((done) => {
|
||||
const selector = new TreeSelectorComponent(
|
||||
tree,
|
||||
currentLeafId,
|
||||
this.ui.terminal.rows,
|
||||
async (entryId) => {
|
||||
// Check if selecting current leaf (no-op)
|
||||
if (entryId === currentLeafId) {
|
||||
done();
|
||||
this.showStatus("Already at this point");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask about summarization
|
||||
done(); // Close selector first
|
||||
|
||||
const wantsSummary = await this.showHookConfirm(
|
||||
"Summarize branch?",
|
||||
"Create a summary of the branch you're leaving?",
|
||||
);
|
||||
|
||||
try {
|
||||
const result = await this.session.navigateTree(entryId, { summarize: wantsSummary });
|
||||
if (result.cancelled) {
|
||||
this.showStatus("Navigation cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update UI
|
||||
this.chatContainer.clear();
|
||||
this.renderInitialMessages();
|
||||
if (result.editorText) {
|
||||
this.editor.setText(result.editorText);
|
||||
}
|
||||
this.showStatus("Navigated to selected point");
|
||||
} catch (error) {
|
||||
this.showError(error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
},
|
||||
() => {
|
||||
done();
|
||||
this.ui.requestRender();
|
||||
},
|
||||
);
|
||||
return { component: selector, focus: selector.getTreeList() };
|
||||
});
|
||||
}
|
||||
|
||||
private showSessionSelector(): void {
|
||||
this.showSelector((done) => {
|
||||
const sessions = SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue