@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Added configurable interactive inline image width via `terminal.imageWidthCells` and `/settings`, so tool-output images are no longer hard-capped to 60 terminal cells ([#3508](https://github.com/badlogic/pi-mono/issues/3508))
|
||||||
- Fixed `sessionDir` in `settings.json` to expand `~`, so portable session-directory settings no longer require a shell wrapper ([#3514](https://github.com/badlogic/pi-mono/issues/3514))
|
- Fixed `sessionDir` in `settings.json` to expand `~`, so portable session-directory settings no longer require a shell wrapper ([#3514](https://github.com/badlogic/pi-mono/issues/3514))
|
||||||
- Fixed parallel tool-call rows to leave the pending state as soon as each tool is finalized, while still appending persisted tool results in assistant source order ([#3503](https://github.com/badlogic/pi-mono/issues/3503))
|
- Fixed parallel tool-call rows to leave the pending state as soon as each tool is finalized, while still appending persisted tool results in assistant source order ([#3503](https://github.com/badlogic/pi-mono/issues/3503))
|
||||||
- Fixed exported session markdown to render Markdown while showing HTML-like message content such as `<file name="...">...</file>` verbatim, so shared sessions match the TUI instead of letting the browser interpret message text ([#3484](https://github.com/badlogic/pi-mono/issues/3484))
|
- Fixed exported session markdown to render Markdown while showing HTML-like message content such as `<file name="...">...</file>` verbatim, so shared sessions match the TUI instead of letting the browser interpret message text ([#3484](https://github.com/badlogic/pi-mono/issues/3484))
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ When a provider requests a retry delay longer than `maxDelayMs` (e.g., Google's
|
|||||||
| Setting | Type | Default | Description |
|
| Setting | Type | Default | Description |
|
||||||
|---------|------|---------|-------------|
|
|---------|------|---------|-------------|
|
||||||
| `terminal.showImages` | boolean | `true` | Show images in terminal (if supported) |
|
| `terminal.showImages` | boolean | `true` | Show images in terminal (if supported) |
|
||||||
|
| `terminal.imageWidthCells` | number | `60` | Preferred inline image width in terminal cells |
|
||||||
| `terminal.clearOnShrink` | boolean | `false` | Clear empty rows when content shrinks (can cause flicker) |
|
| `terminal.clearOnShrink` | boolean | `false` | Clear empty rows when content shrinks (can cause flicker) |
|
||||||
| `images.autoResize` | boolean | `true` | Resize images to 2000x2000 max |
|
| `images.autoResize` | boolean | `true` | Resize images to 2000x2000 max |
|
||||||
| `images.blockImages` | boolean | `false` | Block all images from being sent to LLM |
|
| `images.blockImages` | boolean | `false` | Block all images from being sent to LLM |
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export interface RetrySettings {
|
|||||||
|
|
||||||
export interface TerminalSettings {
|
export interface TerminalSettings {
|
||||||
showImages?: boolean; // default: true (only relevant if terminal supports images)
|
showImages?: boolean; // default: true (only relevant if terminal supports images)
|
||||||
|
imageWidthCells?: number; // default: 60 (preferred inline image width in terminal cells)
|
||||||
clearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)
|
clearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -870,6 +871,23 @@ export class SettingsManager {
|
|||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getImageWidthCells(): number {
|
||||||
|
const width = this.settings.terminal?.imageWidthCells;
|
||||||
|
if (typeof width !== "number" || !Number.isFinite(width)) {
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
return Math.max(1, Math.floor(width));
|
||||||
|
}
|
||||||
|
|
||||||
|
setImageWidthCells(width: number): void {
|
||||||
|
if (!this.globalSettings.terminal) {
|
||||||
|
this.globalSettings.terminal = {};
|
||||||
|
}
|
||||||
|
this.globalSettings.terminal.imageWidthCells = Math.max(1, Math.floor(width));
|
||||||
|
this.markModified("terminal", "imageWidthCells");
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
getClearOnShrink(): boolean {
|
getClearOnShrink(): boolean {
|
||||||
// Settings takes precedence, then env var, then default false
|
// Settings takes precedence, then env var, then default false
|
||||||
if (this.settings.terminal?.clearOnShrink !== undefined) {
|
if (this.settings.terminal?.clearOnShrink !== undefined) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ const THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {
|
|||||||
export interface SettingsConfig {
|
export interface SettingsConfig {
|
||||||
autoCompact: boolean;
|
autoCompact: boolean;
|
||||||
showImages: boolean;
|
showImages: boolean;
|
||||||
|
imageWidthCells: number;
|
||||||
autoResizeImages: boolean;
|
autoResizeImages: boolean;
|
||||||
blockImages: boolean;
|
blockImages: boolean;
|
||||||
enableSkillCommands: boolean;
|
enableSkillCommands: boolean;
|
||||||
@@ -56,6 +57,7 @@ export interface SettingsConfig {
|
|||||||
export interface SettingsCallbacks {
|
export interface SettingsCallbacks {
|
||||||
onAutoCompactChange: (enabled: boolean) => void;
|
onAutoCompactChange: (enabled: boolean) => void;
|
||||||
onShowImagesChange: (enabled: boolean) => void;
|
onShowImagesChange: (enabled: boolean) => void;
|
||||||
|
onImageWidthCellsChange: (width: number) => void;
|
||||||
onAutoResizeImagesChange: (enabled: boolean) => void;
|
onAutoResizeImagesChange: (enabled: boolean) => void;
|
||||||
onBlockImagesChange: (blocked: boolean) => void;
|
onBlockImagesChange: (blocked: boolean) => void;
|
||||||
onEnableSkillCommandsChange: (enabled: boolean) => void;
|
onEnableSkillCommandsChange: (enabled: boolean) => void;
|
||||||
@@ -292,10 +294,17 @@ export class SettingsSelectorComponent extends Container {
|
|||||||
currentValue: config.showImages ? "true" : "false",
|
currentValue: config.showImages ? "true" : "false",
|
||||||
values: ["true", "false"],
|
values: ["true", "false"],
|
||||||
});
|
});
|
||||||
|
items.splice(2, 0, {
|
||||||
|
id: "image-width-cells",
|
||||||
|
label: "Image width",
|
||||||
|
description: "Preferred inline image width in terminal cells",
|
||||||
|
currentValue: String(config.imageWidthCells),
|
||||||
|
values: ["60", "80", "120"],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image auto-resize toggle (always available, affects both attached and read images)
|
// Image auto-resize toggle (always available, affects both attached and read images)
|
||||||
items.splice(supportsImages ? 2 : 1, 0, {
|
items.splice(supportsImages ? 3 : 1, 0, {
|
||||||
id: "auto-resize-images",
|
id: "auto-resize-images",
|
||||||
label: "Auto-resize images",
|
label: "Auto-resize images",
|
||||||
description: "Resize large images to 2000x2000 max for better model compatibility",
|
description: "Resize large images to 2000x2000 max for better model compatibility",
|
||||||
@@ -378,6 +387,9 @@ export class SettingsSelectorComponent extends Container {
|
|||||||
case "show-images":
|
case "show-images":
|
||||||
callbacks.onShowImagesChange(newValue === "true");
|
callbacks.onShowImagesChange(newValue === "true");
|
||||||
break;
|
break;
|
||||||
|
case "image-width-cells":
|
||||||
|
callbacks.onImageWidthCellsChange(parseInt(newValue, 10));
|
||||||
|
break;
|
||||||
case "auto-resize-images":
|
case "auto-resize-images":
|
||||||
callbacks.onAutoResizeImagesChange(newValue === "true");
|
callbacks.onAutoResizeImagesChange(newValue === "true");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { theme } from "../theme/theme.js";
|
|||||||
|
|
||||||
export interface ToolExecutionOptions {
|
export interface ToolExecutionOptions {
|
||||||
showImages?: boolean;
|
showImages?: boolean;
|
||||||
|
imageWidthCells?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ToolExecutionComponent extends Container {
|
export class ToolExecutionComponent extends Container {
|
||||||
@@ -23,6 +24,7 @@ export class ToolExecutionComponent extends Container {
|
|||||||
private args: any;
|
private args: any;
|
||||||
private expanded = false;
|
private expanded = false;
|
||||||
private showImages: boolean;
|
private showImages: boolean;
|
||||||
|
private imageWidthCells: number;
|
||||||
private isPartial = true;
|
private isPartial = true;
|
||||||
private toolDefinition?: ToolDefinition<any, any>;
|
private toolDefinition?: ToolDefinition<any, any>;
|
||||||
private builtInToolDefinition?: ToolDefinition<any, any>;
|
private builtInToolDefinition?: ToolDefinition<any, any>;
|
||||||
@@ -54,6 +56,7 @@ export class ToolExecutionComponent extends Container {
|
|||||||
this.toolDefinition = toolDefinition;
|
this.toolDefinition = toolDefinition;
|
||||||
this.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];
|
this.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];
|
||||||
this.showImages = options.showImages ?? true;
|
this.showImages = options.showImages ?? true;
|
||||||
|
this.imageWidthCells = options.imageWidthCells ?? 60;
|
||||||
this.ui = ui;
|
this.ui = ui;
|
||||||
this.cwd = cwd;
|
this.cwd = cwd;
|
||||||
|
|
||||||
@@ -205,6 +208,11 @@ export class ToolExecutionComponent extends Container {
|
|||||||
this.updateDisplay();
|
this.updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setImageWidthCells(width: number): void {
|
||||||
|
this.imageWidthCells = Math.max(1, Math.floor(width));
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
override invalidate(): void {
|
override invalidate(): void {
|
||||||
super.invalidate();
|
super.invalidate();
|
||||||
this.updateDisplay();
|
this.updateDisplay();
|
||||||
@@ -312,7 +320,7 @@ export class ToolExecutionComponent extends Container {
|
|||||||
imageData,
|
imageData,
|
||||||
imageMimeType,
|
imageMimeType,
|
||||||
{ fallbackColor: (s: string) => theme.fg("toolOutput", s) },
|
{ fallbackColor: (s: string) => theme.fg("toolOutput", s) },
|
||||||
{ maxWidthCells: 60 },
|
{ maxWidthCells: this.imageWidthCells },
|
||||||
);
|
);
|
||||||
this.imageComponents.push(imageComponent);
|
this.imageComponents.push(imageComponent);
|
||||||
this.addChild(imageComponent);
|
this.addChild(imageComponent);
|
||||||
|
|||||||
@@ -2633,6 +2633,7 @@ export class InteractiveMode {
|
|||||||
content.arguments,
|
content.arguments,
|
||||||
{
|
{
|
||||||
showImages: this.settingsManager.getShowImages(),
|
showImages: this.settingsManager.getShowImages(),
|
||||||
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
||||||
},
|
},
|
||||||
this.getRegisteredToolDefinition(content.name),
|
this.getRegisteredToolDefinition(content.name),
|
||||||
this.ui,
|
this.ui,
|
||||||
@@ -2701,6 +2702,7 @@ export class InteractiveMode {
|
|||||||
event.args,
|
event.args,
|
||||||
{
|
{
|
||||||
showImages: this.settingsManager.getShowImages(),
|
showImages: this.settingsManager.getShowImages(),
|
||||||
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
||||||
},
|
},
|
||||||
this.getRegisteredToolDefinition(event.toolName),
|
this.getRegisteredToolDefinition(event.toolName),
|
||||||
this.ui,
|
this.ui,
|
||||||
@@ -3031,7 +3033,10 @@ export class InteractiveMode {
|
|||||||
content.name,
|
content.name,
|
||||||
content.id,
|
content.id,
|
||||||
content.arguments,
|
content.arguments,
|
||||||
{ showImages: this.settingsManager.getShowImages() },
|
{
|
||||||
|
showImages: this.settingsManager.getShowImages(),
|
||||||
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
||||||
|
},
|
||||||
this.getRegisteredToolDefinition(content.name),
|
this.getRegisteredToolDefinition(content.name),
|
||||||
this.ui,
|
this.ui,
|
||||||
this.sessionManager.getCwd(),
|
this.sessionManager.getCwd(),
|
||||||
@@ -3650,6 +3655,7 @@ export class InteractiveMode {
|
|||||||
{
|
{
|
||||||
autoCompact: this.session.autoCompactionEnabled,
|
autoCompact: this.session.autoCompactionEnabled,
|
||||||
showImages: this.settingsManager.getShowImages(),
|
showImages: this.settingsManager.getShowImages(),
|
||||||
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
||||||
autoResizeImages: this.settingsManager.getImageAutoResize(),
|
autoResizeImages: this.settingsManager.getImageAutoResize(),
|
||||||
blockImages: this.settingsManager.getBlockImages(),
|
blockImages: this.settingsManager.getBlockImages(),
|
||||||
enableSkillCommands: this.settingsManager.getEnableSkillCommands(),
|
enableSkillCommands: this.settingsManager.getEnableSkillCommands(),
|
||||||
@@ -3684,6 +3690,14 @@ export class InteractiveMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onImageWidthCellsChange: (width) => {
|
||||||
|
this.settingsManager.setImageWidthCells(width);
|
||||||
|
for (const child of this.chatContainer.children) {
|
||||||
|
if (child instanceof ToolExecutionComponent) {
|
||||||
|
child.setImageWidthCells(width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
onAutoResizeImagesChange: (enabled) => {
|
onAutoResizeImagesChange: (enabled) => {
|
||||||
this.settingsManager.setImageAutoResize(enabled);
|
this.settingsManager.setImageAutoResize(enabled);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user