mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 10:02:23 +00:00
feat(coding-agent): configurable double-escape action (tree vs branch)
Add doubleEscapeAction setting to choose whether double-escape with an empty editor opens /tree (default) or /branch. - Add setting to Settings interface and SettingsManager - Add to /settings UI for easy toggling - Update interactive-mode to respect the setting - Document in README.md settings table fixes #404
This commit is contained in:
parent
17b3a14bfa
commit
42b1e06ad1
6 changed files with 34 additions and 6 deletions
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"customTools": ["packages/coding-agent/examples/custom-tools/todo/index.ts"],
|
|
||||||
"hooks": ["packages/coding-agent/examples/hooks/todo/index.ts"]
|
|
||||||
}
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Configurable double-escape action: choose whether double-escape with empty editor opens `/tree` (default) or `/branch`. Configure via `/settings` or `doubleEscapeAction` in settings.json ([#404](https://github.com/badlogic/pi-mono/issues/404))
|
||||||
- Vertex AI provider (`google-vertex`): access Gemini models via Google Cloud Vertex AI using Application Default Credentials ([#300](https://github.com/badlogic/pi-mono/pull/300) by [@default-anton](https://github.com/default-anton))
|
- Vertex AI provider (`google-vertex`): access Gemini models via Google Cloud Vertex AI using Application Default Credentials ([#300](https://github.com/badlogic/pi-mono/pull/300) by [@default-anton](https://github.com/default-anton))
|
||||||
- Built-in provider overrides in `models.json`: override just `baseUrl` to route a built-in provider through a proxy while keeping all its models, or define `models` to fully replace the provider ([#406](https://github.com/badlogic/pi-mono/pull/406) by [@yevhen](https://github.com/yevhen))
|
- Built-in provider overrides in `models.json`: override just `baseUrl` to route a built-in provider through a proxy while keeping all its models, or define `models` to fully replace the provider ([#406](https://github.com/badlogic/pi-mono/pull/406) by [@yevhen](https://github.com/yevhen))
|
||||||
- Automatic image resizing: images larger than 2000x2000 are resized for better model compatibility. Original dimensions are injected into the prompt. Controlled via `/settings` or `images.autoResize` in settings.json. ([#402](https://github.com/badlogic/pi-mono/pull/402) by [@mitsuhiko](https://github.com/mitsuhiko))
|
- Automatic image resizing: images larger than 2000x2000 are resized for better model compatibility. Original dimensions are injected into the prompt. Controlled via `/settings` or `images.autoResize` in settings.json. ([#402](https://github.com/badlogic/pi-mono/pull/402) by [@mitsuhiko](https://github.com/mitsuhiko))
|
||||||
|
|
|
||||||
|
|
@ -586,6 +586,7 @@ Global `~/.pi/agent/settings.json` stores persistent preferences:
|
||||||
| `retry.baseDelayMs` | Base delay for exponential backoff | `2000` |
|
| `retry.baseDelayMs` | Base delay for exponential backoff | `2000` |
|
||||||
| `terminal.showImages` | Render images inline (supported terminals) | `true` |
|
| `terminal.showImages` | Render images inline (supported terminals) | `true` |
|
||||||
| `images.autoResize` | Auto-resize images to 2000x2000 max for better model compatibility | `true` |
|
| `images.autoResize` | Auto-resize images to 2000x2000 max for better model compatibility | `true` |
|
||||||
|
| `doubleEscapeAction` | Action for double-escape with empty editor: `tree` or `branch` | `tree` |
|
||||||
| `hooks` | Additional hook file paths | `[]` |
|
| `hooks` | Additional hook file paths | `[]` |
|
||||||
| `customTools` | Additional custom tool file paths | `[]` |
|
| `customTools` | Additional custom tool file paths | `[]` |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ export interface Settings {
|
||||||
terminal?: TerminalSettings;
|
terminal?: TerminalSettings;
|
||||||
images?: ImageSettings;
|
images?: ImageSettings;
|
||||||
enabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)
|
enabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)
|
||||||
|
doubleEscapeAction?: "branch" | "tree"; // Action for double-escape with empty editor (default: "tree")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deep merge settings: project/overrides take precedence, nested objects merge recursively */
|
/** Deep merge settings: project/overrides take precedence, nested objects merge recursively */
|
||||||
|
|
@ -410,4 +411,13 @@ export class SettingsManager {
|
||||||
getEnabledModels(): string[] | undefined {
|
getEnabledModels(): string[] | undefined {
|
||||||
return this.settings.enabledModels;
|
return this.settings.enabledModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDoubleEscapeAction(): "branch" | "tree" {
|
||||||
|
return this.settings.doubleEscapeAction ?? "tree";
|
||||||
|
}
|
||||||
|
|
||||||
|
setDoubleEscapeAction(action: "branch" | "tree"): void {
|
||||||
|
this.globalSettings.doubleEscapeAction = action;
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ export interface SettingsConfig {
|
||||||
availableThemes: string[];
|
availableThemes: string[];
|
||||||
hideThinkingBlock: boolean;
|
hideThinkingBlock: boolean;
|
||||||
collapseChangelog: boolean;
|
collapseChangelog: boolean;
|
||||||
|
doubleEscapeAction: "branch" | "tree";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SettingsCallbacks {
|
export interface SettingsCallbacks {
|
||||||
|
|
@ -46,6 +47,7 @@ export interface SettingsCallbacks {
|
||||||
onThemePreview?: (theme: string) => void;
|
onThemePreview?: (theme: string) => void;
|
||||||
onHideThinkingBlockChange: (hidden: boolean) => void;
|
onHideThinkingBlockChange: (hidden: boolean) => void;
|
||||||
onCollapseChangelogChange: (collapsed: boolean) => void;
|
onCollapseChangelogChange: (collapsed: boolean) => void;
|
||||||
|
onDoubleEscapeActionChange: (action: "branch" | "tree") => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,6 +162,13 @@ export class SettingsSelectorComponent extends Container {
|
||||||
currentValue: config.collapseChangelog ? "true" : "false",
|
currentValue: config.collapseChangelog ? "true" : "false",
|
||||||
values: ["true", "false"],
|
values: ["true", "false"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "double-escape-action",
|
||||||
|
label: "Double-escape action",
|
||||||
|
description: "Action when pressing Escape twice with empty editor",
|
||||||
|
currentValue: config.doubleEscapeAction,
|
||||||
|
values: ["tree", "branch"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "thinking",
|
id: "thinking",
|
||||||
label: "Thinking level",
|
label: "Thinking level",
|
||||||
|
|
@ -264,6 +273,9 @@ export class SettingsSelectorComponent extends Container {
|
||||||
case "collapse-changelog":
|
case "collapse-changelog":
|
||||||
callbacks.onCollapseChangelogChange(newValue === "true");
|
callbacks.onCollapseChangelogChange(newValue === "true");
|
||||||
break;
|
break;
|
||||||
|
case "double-escape-action":
|
||||||
|
callbacks.onDoubleEscapeActionChange(newValue as "branch" | "tree");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callbacks.onCancel,
|
callbacks.onCancel,
|
||||||
|
|
|
||||||
|
|
@ -755,10 +755,14 @@ export class InteractiveMode {
|
||||||
this.isBashMode = false;
|
this.isBashMode = false;
|
||||||
this.updateEditorBorderColor();
|
this.updateEditorBorderColor();
|
||||||
} else if (!this.editor.getText().trim()) {
|
} else if (!this.editor.getText().trim()) {
|
||||||
// Double-escape with empty editor triggers /branch
|
// Double-escape with empty editor triggers /tree or /branch based on setting
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (now - this.lastEscapeTime < 500) {
|
if (now - this.lastEscapeTime < 500) {
|
||||||
this.showUserMessageSelector();
|
if (this.settingsManager.getDoubleEscapeAction() === "tree") {
|
||||||
|
this.showTreeSelector();
|
||||||
|
} else {
|
||||||
|
this.showUserMessageSelector();
|
||||||
|
}
|
||||||
this.lastEscapeTime = 0;
|
this.lastEscapeTime = 0;
|
||||||
} else {
|
} else {
|
||||||
this.lastEscapeTime = now;
|
this.lastEscapeTime = now;
|
||||||
|
|
@ -1682,6 +1686,7 @@ export class InteractiveMode {
|
||||||
availableThemes: getAvailableThemes(),
|
availableThemes: getAvailableThemes(),
|
||||||
hideThinkingBlock: this.hideThinkingBlock,
|
hideThinkingBlock: this.hideThinkingBlock,
|
||||||
collapseChangelog: this.settingsManager.getCollapseChangelog(),
|
collapseChangelog: this.settingsManager.getCollapseChangelog(),
|
||||||
|
doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onAutoCompactChange: (enabled) => {
|
onAutoCompactChange: (enabled) => {
|
||||||
|
|
@ -1739,6 +1744,9 @@ export class InteractiveMode {
|
||||||
onCollapseChangelogChange: (collapsed) => {
|
onCollapseChangelogChange: (collapsed) => {
|
||||||
this.settingsManager.setCollapseChangelog(collapsed);
|
this.settingsManager.setCollapseChangelog(collapsed);
|
||||||
},
|
},
|
||||||
|
onDoubleEscapeActionChange: (action) => {
|
||||||
|
this.settingsManager.setDoubleEscapeAction(action);
|
||||||
|
},
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
done();
|
done();
|
||||||
this.ui.requestRender();
|
this.ui.requestRender();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue