mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 19:05:11 +00:00
Add global debug key (Shift+Ctrl+D), iterative tree sorting to avoid stack overflow
This commit is contained in:
parent
1f4594598b
commit
544814875e
5 changed files with 30 additions and 6 deletions
|
|
@ -789,7 +789,7 @@ export class SessionManager {
|
|||
// Build tree
|
||||
for (const entry of entries) {
|
||||
const node = nodeMap.get(entry.id)!;
|
||||
if (entry.parentId === null) {
|
||||
if (entry.parentId === null || entry.parentId === entry.id) {
|
||||
roots.push(node);
|
||||
} else {
|
||||
const parent = nodeMap.get(entry.parentId);
|
||||
|
|
@ -803,11 +803,13 @@ export class SessionManager {
|
|||
}
|
||||
|
||||
// Sort children by timestamp (oldest first, newest at bottom)
|
||||
const sortChildren = (node: SessionTreeNode): void => {
|
||||
// Use iterative approach to avoid stack overflow on deep trees
|
||||
const stack: SessionTreeNode[] = [...roots];
|
||||
while (stack.length > 0) {
|
||||
const node = stack.pop()!;
|
||||
node.children.sort((a, b) => new Date(a.entry.timestamp).getTime() - new Date(b.entry.timestamp).getTime());
|
||||
node.children.forEach(sortChildren);
|
||||
};
|
||||
roots.forEach(sortChildren);
|
||||
stack.push(...node.children);
|
||||
}
|
||||
|
||||
return roots;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@ export class InteractiveMode {
|
|||
this.editor.onShiftTab = () => this.cycleThinkingLevel();
|
||||
this.editor.onCtrlP = () => this.cycleModel("forward");
|
||||
this.editor.onShiftCtrlP = () => this.cycleModel("backward");
|
||||
|
||||
// Global debug handler on TUI (works regardless of focus)
|
||||
this.ui.onDebug = () => this.handleDebugCommand();
|
||||
this.editor.onCtrlL = () => this.showModelSelector();
|
||||
this.editor.onCtrlO = () => this.toggleToolOutputExpansion();
|
||||
this.editor.onCtrlT = () => this.toggleThinkingBlockVisibility();
|
||||
|
|
@ -1645,7 +1648,7 @@ export class InteractiveMode {
|
|||
this.ui.requestRender();
|
||||
},
|
||||
);
|
||||
return { component: selector, focus: selector.getTreeList() };
|
||||
return { component: selector, focus: selector };
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export {
|
|||
isEnter,
|
||||
isEscape,
|
||||
isHome,
|
||||
isShiftCtrlD,
|
||||
isShiftCtrlP,
|
||||
isShiftEnter,
|
||||
isShiftTab,
|
||||
|
|
|
|||
|
|
@ -320,6 +320,14 @@ export function isShiftCtrlP(data: string): boolean {
|
|||
return matchesKittySequence(data, CODEPOINTS.p, MODIFIERS.shift + MODIFIERS.ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if input matches Shift+Ctrl+D (Kitty protocol only, for debug).
|
||||
* Ignores lock key bits.
|
||||
*/
|
||||
export function isShiftCtrlD(data: string): boolean {
|
||||
return matchesKittySequence(data, CODEPOINTS.d, MODIFIERS.shift + MODIFIERS.ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if input matches Ctrl+T (raw byte or Kitty protocol).
|
||||
* Ignores lock key bits.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
import * as fs from "node:fs";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import { isShiftCtrlD } from "./keys.js";
|
||||
import type { Terminal } from "./terminal.js";
|
||||
import { getCapabilities, setCellDimensions } from "./terminal-image.js";
|
||||
import { visibleWidth } from "./utils.js";
|
||||
|
|
@ -78,6 +79,9 @@ export class TUI extends Container {
|
|||
private previousLines: string[] = [];
|
||||
private previousWidth = 0;
|
||||
private focusedComponent: Component | null = null;
|
||||
|
||||
/** Global callback for debug key (Shift+Ctrl+D). Called before input is forwarded to focused component. */
|
||||
public onDebug?: () => void;
|
||||
private renderRequested = false;
|
||||
private cursorRow = 0; // Track where cursor is (0-indexed, relative to our first line)
|
||||
private inputBuffer = ""; // Buffer for parsing terminal responses
|
||||
|
|
@ -141,6 +145,12 @@ export class TUI extends Container {
|
|||
data = filtered;
|
||||
}
|
||||
|
||||
// Global debug key handler (Shift+Ctrl+D)
|
||||
if (isShiftCtrlD(data) && this.onDebug) {
|
||||
this.onDebug();
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass input to focused component (including Ctrl+C)
|
||||
// The focused component can decide how to handle Ctrl+C
|
||||
if (this.focusedComponent?.handleInput) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue