chore: drop non-code junk (pi-mono-reference, runtime state, root duplicates)
Remove files that should never have been tracked: - pi-mono-reference/: 688-file copy of an upstream monorepo, zero imports, used only as offline human reference - build/electron-builder.runtime.json: environment-specific build artifact with hardcoded local paths - state/cancel-signal-state.json: runtime state written by the app - prompt.txt, logo.svg (root): exact duplicates of the canonical copies under .planning/archive/ and assets/ Add state/ to .gitignore so future runtime state stays out.
This commit is contained in:
1 parent
34ca5b77f1
commit
1f7230fe87
691 files changed
+3
-190434
No files matched your search
-444
@@ -1,444 +0,0 @@
|
||||
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
|
||||
import type { Transport } from "@mariozechner/pi-ai";
|
||||
import {
|
||||
Container,
|
||||
getCapabilities,
|
||||
type SelectItem,
|
||||
SelectList,
|
||||
type SelectListLayoutOptions,
|
||||
type SettingItem,
|
||||
SettingsList,
|
||||
Spacer,
|
||||
Text,
|
||||
} from "@mariozechner/pi-tui";
|
||||
import { getSelectListTheme, getSettingsListTheme, theme } from "../theme/theme.js";
|
||||
import { DynamicBorder } from "./dynamic-border.js";
|
||||
|
||||
const SETTINGS_SUBMENU_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {
|
||||
minPrimaryColumnWidth: 12,
|
||||
maxPrimaryColumnWidth: 32,
|
||||
};
|
||||
|
||||
const THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {
|
||||
off: "No reasoning",
|
||||
minimal: "Very brief reasoning (~1k tokens)",
|
||||
low: "Light reasoning (~2k tokens)",
|
||||
medium: "Moderate reasoning (~8k tokens)",
|
||||
high: "Deep reasoning (~16k tokens)",
|
||||
xhigh: "Maximum reasoning (~32k tokens)",
|
||||
};
|
||||
|
||||
export interface SettingsConfig {
|
||||
autoCompact: boolean;
|
||||
showImages: boolean;
|
||||
autoResizeImages: boolean;
|
||||
blockImages: boolean;
|
||||
enableSkillCommands: boolean;
|
||||
steeringMode: "all" | "one-at-a-time";
|
||||
followUpMode: "all" | "one-at-a-time";
|
||||
transport: Transport;
|
||||
thinkingLevel: ThinkingLevel;
|
||||
availableThinkingLevels: ThinkingLevel[];
|
||||
currentTheme: string;
|
||||
availableThemes: string[];
|
||||
hideThinkingBlock: boolean;
|
||||
collapseChangelog: boolean;
|
||||
enableInstallTelemetry: boolean;
|
||||
doubleEscapeAction: "fork" | "tree" | "none";
|
||||
treeFilterMode: "default" | "no-tools" | "user-only" | "labeled-only" | "all";
|
||||
showHardwareCursor: boolean;
|
||||
editorPaddingX: number;
|
||||
autocompleteMaxVisible: number;
|
||||
quietStartup: boolean;
|
||||
clearOnShrink: boolean;
|
||||
}
|
||||
|
||||
export interface SettingsCallbacks {
|
||||
onAutoCompactChange: (enabled: boolean) => void;
|
||||
onShowImagesChange: (enabled: boolean) => void;
|
||||
onAutoResizeImagesChange: (enabled: boolean) => void;
|
||||
onBlockImagesChange: (blocked: boolean) => void;
|
||||
onEnableSkillCommandsChange: (enabled: boolean) => void;
|
||||
onSteeringModeChange: (mode: "all" | "one-at-a-time") => void;
|
||||
onFollowUpModeChange: (mode: "all" | "one-at-a-time") => void;
|
||||
onTransportChange: (transport: Transport) => void;
|
||||
onThinkingLevelChange: (level: ThinkingLevel) => void;
|
||||
onThemeChange: (theme: string) => void;
|
||||
onThemePreview?: (theme: string) => void;
|
||||
onHideThinkingBlockChange: (hidden: boolean) => void;
|
||||
onCollapseChangelogChange: (collapsed: boolean) => void;
|
||||
onEnableInstallTelemetryChange: (enabled: boolean) => void;
|
||||
onDoubleEscapeActionChange: (action: "fork" | "tree" | "none") => void;
|
||||
onTreeFilterModeChange: (mode: "default" | "no-tools" | "user-only" | "labeled-only" | "all") => void;
|
||||
onShowHardwareCursorChange: (enabled: boolean) => void;
|
||||
onEditorPaddingXChange: (padding: number) => void;
|
||||
onAutocompleteMaxVisibleChange: (maxVisible: number) => void;
|
||||
onQuietStartupChange: (enabled: boolean) => void;
|
||||
onClearOnShrinkChange: (enabled: boolean) => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A submenu component for selecting from a list of options.
|
||||
*/
|
||||
class SelectSubmenu extends Container {
|
||||
private selectList: SelectList;
|
||||
|
||||
constructor(
|
||||
title: string,
|
||||
description: string,
|
||||
options: SelectItem[],
|
||||
currentValue: string,
|
||||
onSelect: (value: string) => void,
|
||||
onCancel: () => void,
|
||||
onSelectionChange?: (value: string) => void,
|
||||
) {
|
||||
super();
|
||||
|
||||
// Title
|
||||
this.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
|
||||
|
||||
// Description
|
||||
if (description) {
|
||||
this.addChild(new Spacer(1));
|
||||
this.addChild(new Text(theme.fg("muted", description), 0, 0));
|
||||
}
|
||||
|
||||
// Spacer
|
||||
this.addChild(new Spacer(1));
|
||||
|
||||
// Select list
|
||||
this.selectList = new SelectList(
|
||||
options,
|
||||
Math.min(options.length, 10),
|
||||
getSelectListTheme(),
|
||||
SETTINGS_SUBMENU_SELECT_LIST_LAYOUT,
|
||||
);
|
||||
|
||||
// Pre-select current value
|
||||
const currentIndex = options.findIndex((o) => o.value === currentValue);
|
||||
if (currentIndex !== -1) {
|
||||
this.selectList.setSelectedIndex(currentIndex);
|
||||
}
|
||||
|
||||
this.selectList.onSelect = (item) => {
|
||||
onSelect(item.value);
|
||||
};
|
||||
|
||||
this.selectList.onCancel = onCancel;
|
||||
|
||||
if (onSelectionChange) {
|
||||
this.selectList.onSelectionChange = (item) => {
|
||||
onSelectionChange(item.value);
|
||||
};
|
||||
}
|
||||
|
||||
this.addChild(this.selectList);
|
||||
|
||||
// Hint
|
||||
this.addChild(new Spacer(1));
|
||||
this.addChild(new Text(theme.fg("dim", " Enter to select · Esc to go back"), 0, 0));
|
||||
}
|
||||
|
||||
handleInput(data: string): void {
|
||||
this.selectList.handleInput(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main settings selector component.
|
||||
*/
|
||||
export class SettingsSelectorComponent extends Container {
|
||||
private settingsList: SettingsList;
|
||||
|
||||
constructor(config: SettingsConfig, callbacks: SettingsCallbacks) {
|
||||
super();
|
||||
|
||||
const supportsImages = getCapabilities().images;
|
||||
|
||||
const items: SettingItem[] = [
|
||||
{
|
||||
id: "autocompact",
|
||||
label: "Auto-compact",
|
||||
description: "Automatically compact context when it gets too large",
|
||||
currentValue: config.autoCompact ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
},
|
||||
{
|
||||
id: "steering-mode",
|
||||
label: "Steering mode",
|
||||
description:
|
||||
"Enter while streaming queues steering messages. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.",
|
||||
currentValue: config.steeringMode,
|
||||
values: ["one-at-a-time", "all"],
|
||||
},
|
||||
{
|
||||
id: "follow-up-mode",
|
||||
label: "Follow-up mode",
|
||||
description:
|
||||
"Alt+Enter queues follow-up messages until agent stops. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.",
|
||||
currentValue: config.followUpMode,
|
||||
values: ["one-at-a-time", "all"],
|
||||
},
|
||||
{
|
||||
id: "transport",
|
||||
label: "Transport",
|
||||
description: "Preferred transport for providers that support multiple transports",
|
||||
currentValue: config.transport,
|
||||
values: ["sse", "websocket", "auto"],
|
||||
},
|
||||
{
|
||||
id: "hide-thinking",
|
||||
label: "Hide thinking",
|
||||
description: "Hide thinking blocks in assistant responses",
|
||||
currentValue: config.hideThinkingBlock ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
},
|
||||
{
|
||||
id: "collapse-changelog",
|
||||
label: "Collapse changelog",
|
||||
description: "Show condensed changelog after updates",
|
||||
currentValue: config.collapseChangelog ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
},
|
||||
{
|
||||
id: "quiet-startup",
|
||||
label: "Quiet startup",
|
||||
description: "Disable verbose printing at startup",
|
||||
currentValue: config.quietStartup ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
},
|
||||
{
|
||||
id: "install-telemetry",
|
||||
label: "Install telemetry",
|
||||
description: "Send an anonymous version/update ping after changelog-detected updates",
|
||||
currentValue: config.enableInstallTelemetry ? "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", "fork", "none"],
|
||||
},
|
||||
{
|
||||
id: "tree-filter-mode",
|
||||
label: "Tree filter mode",
|
||||
description: "Default filter when opening /tree",
|
||||
currentValue: config.treeFilterMode,
|
||||
values: ["default", "no-tools", "user-only", "labeled-only", "all"],
|
||||
},
|
||||
{
|
||||
id: "thinking",
|
||||
label: "Thinking level",
|
||||
description: "Reasoning depth for thinking-capable models",
|
||||
currentValue: config.thinkingLevel,
|
||||
submenu: (currentValue, done) =>
|
||||
new SelectSubmenu(
|
||||
"Thinking Level",
|
||||
"Select reasoning depth for thinking-capable models",
|
||||
config.availableThinkingLevels.map((level) => ({
|
||||
value: level,
|
||||
label: level,
|
||||
description: THINKING_DESCRIPTIONS[level],
|
||||
})),
|
||||
currentValue,
|
||||
(value) => {
|
||||
callbacks.onThinkingLevelChange(value as ThinkingLevel);
|
||||
done(value);
|
||||
},
|
||||
() => done(),
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "theme",
|
||||
label: "Theme",
|
||||
description: "Color theme for the interface",
|
||||
currentValue: config.currentTheme,
|
||||
submenu: (currentValue, done) =>
|
||||
new SelectSubmenu(
|
||||
"Theme",
|
||||
"Select color theme",
|
||||
config.availableThemes.map((t) => ({
|
||||
value: t,
|
||||
label: t,
|
||||
})),
|
||||
currentValue,
|
||||
(value) => {
|
||||
callbacks.onThemeChange(value);
|
||||
done(value);
|
||||
},
|
||||
() => {
|
||||
// Restore original theme on cancel
|
||||
callbacks.onThemePreview?.(currentValue);
|
||||
done();
|
||||
},
|
||||
(value) => {
|
||||
// Preview theme on selection change
|
||||
callbacks.onThemePreview?.(value);
|
||||
},
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// Only show image toggle if terminal supports it
|
||||
if (supportsImages) {
|
||||
// Insert after autocompact
|
||||
items.splice(1, 0, {
|
||||
id: "show-images",
|
||||
label: "Show images",
|
||||
description: "Render images inline in terminal",
|
||||
currentValue: config.showImages ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
});
|
||||
}
|
||||
|
||||
// Image auto-resize toggle (always available, affects both attached and read images)
|
||||
items.splice(supportsImages ? 2 : 1, 0, {
|
||||
id: "auto-resize-images",
|
||||
label: "Auto-resize images",
|
||||
description: "Resize large images to 2000x2000 max for better model compatibility",
|
||||
currentValue: config.autoResizeImages ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
});
|
||||
|
||||
// Block images toggle (always available, insert after auto-resize-images)
|
||||
const autoResizeIndex = items.findIndex((item) => item.id === "auto-resize-images");
|
||||
items.splice(autoResizeIndex + 1, 0, {
|
||||
id: "block-images",
|
||||
label: "Block images",
|
||||
description: "Prevent images from being sent to LLM providers",
|
||||
currentValue: config.blockImages ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
});
|
||||
|
||||
// Skill commands toggle (insert after block-images)
|
||||
const blockImagesIndex = items.findIndex((item) => item.id === "block-images");
|
||||
items.splice(blockImagesIndex + 1, 0, {
|
||||
id: "skill-commands",
|
||||
label: "Skill commands",
|
||||
description: "Register skills as /skill:name commands",
|
||||
currentValue: config.enableSkillCommands ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
});
|
||||
|
||||
// Hardware cursor toggle (insert after skill-commands)
|
||||
const skillCommandsIndex = items.findIndex((item) => item.id === "skill-commands");
|
||||
items.splice(skillCommandsIndex + 1, 0, {
|
||||
id: "show-hardware-cursor",
|
||||
label: "Show hardware cursor",
|
||||
description: "Show the terminal cursor while still positioning it for IME support",
|
||||
currentValue: config.showHardwareCursor ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
});
|
||||
|
||||
// Editor padding toggle (insert after show-hardware-cursor)
|
||||
const hardwareCursorIndex = items.findIndex((item) => item.id === "show-hardware-cursor");
|
||||
items.splice(hardwareCursorIndex + 1, 0, {
|
||||
id: "editor-padding",
|
||||
label: "Editor padding",
|
||||
description: "Horizontal padding for input editor (0-3)",
|
||||
currentValue: String(config.editorPaddingX),
|
||||
values: ["0", "1", "2", "3"],
|
||||
});
|
||||
|
||||
// Autocomplete max visible toggle (insert after editor-padding)
|
||||
const editorPaddingIndex = items.findIndex((item) => item.id === "editor-padding");
|
||||
items.splice(editorPaddingIndex + 1, 0, {
|
||||
id: "autocomplete-max-visible",
|
||||
label: "Autocomplete max items",
|
||||
description: "Max visible items in autocomplete dropdown (3-20)",
|
||||
currentValue: String(config.autocompleteMaxVisible),
|
||||
values: ["3", "5", "7", "10", "15", "20"],
|
||||
});
|
||||
|
||||
// Clear on shrink toggle (insert after autocomplete-max-visible)
|
||||
const autocompleteIndex = items.findIndex((item) => item.id === "autocomplete-max-visible");
|
||||
items.splice(autocompleteIndex + 1, 0, {
|
||||
id: "clear-on-shrink",
|
||||
label: "Clear on shrink",
|
||||
description: "Clear empty rows when content shrinks (may cause flicker)",
|
||||
currentValue: config.clearOnShrink ? "true" : "false",
|
||||
values: ["true", "false"],
|
||||
});
|
||||
|
||||
// Add borders
|
||||
this.addChild(new DynamicBorder());
|
||||
|
||||
this.settingsList = new SettingsList(
|
||||
items,
|
||||
10,
|
||||
getSettingsListTheme(),
|
||||
(id, newValue) => {
|
||||
switch (id) {
|
||||
case "autocompact":
|
||||
callbacks.onAutoCompactChange(newValue === "true");
|
||||
break;
|
||||
case "show-images":
|
||||
callbacks.onShowImagesChange(newValue === "true");
|
||||
break;
|
||||
case "auto-resize-images":
|
||||
callbacks.onAutoResizeImagesChange(newValue === "true");
|
||||
break;
|
||||
case "block-images":
|
||||
callbacks.onBlockImagesChange(newValue === "true");
|
||||
break;
|
||||
case "skill-commands":
|
||||
callbacks.onEnableSkillCommandsChange(newValue === "true");
|
||||
break;
|
||||
case "steering-mode":
|
||||
callbacks.onSteeringModeChange(newValue as "all" | "one-at-a-time");
|
||||
break;
|
||||
case "follow-up-mode":
|
||||
callbacks.onFollowUpModeChange(newValue as "all" | "one-at-a-time");
|
||||
break;
|
||||
case "transport":
|
||||
callbacks.onTransportChange(newValue as Transport);
|
||||
break;
|
||||
case "hide-thinking":
|
||||
callbacks.onHideThinkingBlockChange(newValue === "true");
|
||||
break;
|
||||
case "collapse-changelog":
|
||||
callbacks.onCollapseChangelogChange(newValue === "true");
|
||||
break;
|
||||
case "quiet-startup":
|
||||
callbacks.onQuietStartupChange(newValue === "true");
|
||||
break;
|
||||
case "install-telemetry":
|
||||
callbacks.onEnableInstallTelemetryChange(newValue === "true");
|
||||
break;
|
||||
case "double-escape-action":
|
||||
callbacks.onDoubleEscapeActionChange(newValue as "fork" | "tree");
|
||||
break;
|
||||
case "tree-filter-mode":
|
||||
callbacks.onTreeFilterModeChange(
|
||||
newValue as "default" | "no-tools" | "user-only" | "labeled-only" | "all",
|
||||
);
|
||||
break;
|
||||
case "show-hardware-cursor":
|
||||
callbacks.onShowHardwareCursorChange(newValue === "true");
|
||||
break;
|
||||
case "editor-padding":
|
||||
callbacks.onEditorPaddingXChange(parseInt(newValue, 10));
|
||||
break;
|
||||
case "autocomplete-max-visible":
|
||||
callbacks.onAutocompleteMaxVisibleChange(parseInt(newValue, 10));
|
||||
break;
|
||||
case "clear-on-shrink":
|
||||
callbacks.onClearOnShrinkChange(newValue === "true");
|
||||
break;
|
||||
}
|
||||
},
|
||||
callbacks.onCancel,
|
||||
{ enableSearch: true },
|
||||
);
|
||||
|
||||
this.addChild(this.settingsList);
|
||||
this.addChild(new DynamicBorder());
|
||||
}
|
||||
|
||||
getSettingsList(): SettingsList {
|
||||
return this.settingsList;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user