mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 06:04:15 +00:00
Fix message editor height adjustment, requires Chrome +123
This commit is contained in:
parent
b6b64dff86
commit
92f8801864
11 changed files with 41 additions and 38 deletions
|
|
@ -29,6 +29,8 @@ export class AgentInterface extends LitElement {
|
|||
@property({ attribute: false }) onBeforeSend?: () => void | Promise<void>;
|
||||
// Optional callback called before executing a tool call - return false to prevent execution
|
||||
@property({ attribute: false }) onBeforeToolCall?: (toolName: string, args: any) => boolean | Promise<boolean>;
|
||||
// Optional callback called when cost display is clicked
|
||||
@property({ attribute: false }) onCostClick?: () => void;
|
||||
|
||||
// References
|
||||
@query("message-editor") private _messageEditor!: MessageEditor;
|
||||
|
|
@ -226,6 +228,7 @@ export class AgentInterface extends LitElement {
|
|||
.tools=${state.tools}
|
||||
.pendingToolCalls=${this.session ? this.session.state.pendingToolCalls : new Set<string>()}
|
||||
.isStreaming=${state.isStreaming}
|
||||
.onCostClick=${this.onCostClick}
|
||||
></message-list>
|
||||
|
||||
<!-- Streaming message container - manages its own updates -->
|
||||
|
|
@ -235,6 +238,7 @@ export class AgentInterface extends LitElement {
|
|||
.isStreaming=${state.isStreaming}
|
||||
.pendingToolCalls=${state.pendingToolCalls}
|
||||
.toolResultsById=${toolResultsById}
|
||||
.onCostClick=${this.onCostClick}
|
||||
></streaming-message-container>
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -275,7 +279,15 @@ export class AgentInterface extends LitElement {
|
|||
<div class="flex items-center gap-1">
|
||||
${this.showThemeToggle ? html`<theme-toggle></theme-toggle>` : html``}
|
||||
</div>
|
||||
<div class="flex ml-auto items-center gap-3">${totalsText ? html`<span>${totalsText}</span>` : ""}</div>
|
||||
<div class="flex ml-auto items-center gap-3">
|
||||
${
|
||||
totalsText
|
||||
? this.onCostClick
|
||||
? html`<span class="cursor-pointer hover:text-foreground transition-colors" @click=${this.onCostClick}>${totalsText}</span>`
|
||||
: html`<span>${totalsText}</span>`
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,6 @@ export class MessageEditor extends LitElement {
|
|||
const oldValue = this._value;
|
||||
this._value = val;
|
||||
this.requestUpdate("value", oldValue);
|
||||
this.updateComplete.then(() => {
|
||||
const textarea = this.textareaRef.value;
|
||||
if (textarea) {
|
||||
textarea.style.height = "auto";
|
||||
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@property() isStreaming = false;
|
||||
|
|
@ -60,8 +53,6 @@ export class MessageEditor extends LitElement {
|
|||
private handleTextareaInput = (e: Event) => {
|
||||
const textarea = e.target as HTMLTextAreaElement;
|
||||
this.value = textarea.value;
|
||||
textarea.style.height = "auto";
|
||||
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
||||
this.onInput?.(this.value);
|
||||
};
|
||||
|
||||
|
|
@ -231,33 +222,13 @@ export class MessageEditor extends LitElement {
|
|||
this.processingFiles = false;
|
||||
};
|
||||
|
||||
private adjustTextareaHeight() {
|
||||
const textarea = this.textareaRef.value;
|
||||
if (textarea) {
|
||||
// Reset height to auto to get accurate scrollHeight
|
||||
textarea.style.height = "auto";
|
||||
// Only adjust if there's content, otherwise keep minimal height
|
||||
if (this.value.trim()) {
|
||||
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override firstUpdated() {
|
||||
const textarea = this.textareaRef.value;
|
||||
if (textarea) {
|
||||
// Don't adjust height on first render - let it be minimal
|
||||
textarea.focus();
|
||||
}
|
||||
}
|
||||
|
||||
override updated() {
|
||||
// Only adjust height when component updates if there's content
|
||||
if (this.value) {
|
||||
this.adjustTextareaHeight();
|
||||
}
|
||||
}
|
||||
|
||||
override render() {
|
||||
// Check if current model supports thinking/reasoning
|
||||
const model = this.currentModel;
|
||||
|
|
@ -304,7 +275,7 @@ export class MessageEditor extends LitElement {
|
|||
class="w-full bg-transparent p-4 text-foreground placeholder-muted-foreground outline-none resize-none overflow-y-auto"
|
||||
placeholder=${i18n("Type a message...")}
|
||||
rows="1"
|
||||
style="max-height: 200px;"
|
||||
style="max-height: 200px; field-sizing: content; min-height: 1lh; height: auto;"
|
||||
.value=${this.value}
|
||||
@input=${this.handleTextareaInput}
|
||||
@keydown=${this.handleKeyDown}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export class MessageList extends LitElement {
|
|||
@property({ type: Array }) tools: AgentTool[] = [];
|
||||
@property({ type: Object }) pendingToolCalls?: Set<string>;
|
||||
@property({ type: Boolean }) isStreaming: boolean = false;
|
||||
@property({ attribute: false }) onCostClick?: () => void;
|
||||
|
||||
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
||||
return this;
|
||||
|
|
@ -68,6 +69,7 @@ export class MessageList extends LitElement {
|
|||
.pendingToolCalls=${this.pendingToolCalls}
|
||||
.toolResultsById=${resultByCallId}
|
||||
.hideToolCalls=${false}
|
||||
.onCostClick=${this.onCostClick}
|
||||
></assistant-message>`,
|
||||
});
|
||||
index++;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ export class AssistantMessage extends LitElement {
|
|||
@property({ type: Boolean }) hideToolCalls = false;
|
||||
@property({ type: Object }) toolResultsById?: Map<string, ToolResultMessageType>;
|
||||
@property({ type: Boolean }) isStreaming: boolean = false;
|
||||
@property({ attribute: false }) onCostClick?: () => void;
|
||||
|
||||
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
||||
return this;
|
||||
|
|
@ -133,7 +134,9 @@ export class AssistantMessage extends LitElement {
|
|||
${orderedParts.length ? html` <div class="px-4 flex flex-col gap-3">${orderedParts}</div> ` : ""}
|
||||
${
|
||||
this.message.usage
|
||||
? html` <div class="px-4 mt-2 text-xs text-muted-foreground">${formatUsage(this.message.usage)}</div> `
|
||||
? this.onCostClick
|
||||
? html` <div class="px-4 mt-2 text-xs text-muted-foreground cursor-pointer hover:text-foreground transition-colors" @click=${this.onCostClick}>${formatUsage(this.message.usage)}</div> `
|
||||
: html` <div class="px-4 mt-2 text-xs text-muted-foreground">${formatUsage(this.message.usage)}</div> `
|
||||
: ""
|
||||
}
|
||||
${
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export class StreamingMessageContainer extends LitElement {
|
|||
@property({ type: Boolean }) isStreaming = false;
|
||||
@property({ type: Object }) pendingToolCalls?: Set<string>;
|
||||
@property({ type: Object }) toolResultsById?: Map<string, ToolResultMessage>;
|
||||
@property({ attribute: false }) onCostClick?: () => void;
|
||||
|
||||
@state() private _message: Message | null = null;
|
||||
private _pendingMessage: Message | null = null;
|
||||
|
|
@ -87,6 +88,7 @@ export class StreamingMessageContainer extends LitElement {
|
|||
.pendingToolCalls=${this.pendingToolCalls}
|
||||
.toolResultsById=${this.toolResultsById}
|
||||
.hideToolCalls=${false}
|
||||
.onCostClick=${this.onCostClick}
|
||||
></assistant-message>
|
||||
${this.isStreaming ? html`<span class="mx-4 inline-block w-2 h-4 bg-muted-foreground animate-pulse"></span>` : ""}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue