refactor(vscode-ide-companion/panel): reimplement editor group locking with proper error handling

This commit is contained in:
yiliang114
2025-12-03 01:03:10 +08:00
parent c6299bf135
commit 05f5189bb4
6 changed files with 151 additions and 37 deletions

View File

@@ -161,17 +161,24 @@ export class PanelManager {
/**
* Auto-lock editor group (only called when creating a new Panel)
* Note: We no longer auto-lock Qwen Code group to allow users to create multiple Qwen Code tabs
* After creating/revealing the WebviewPanel, lock the active editor group so
* the group stays dedicated (users can still unlock manually). We still
* temporarily unlock before creation to allow adding tabs to an existing
* group; this method restores the locked state afterwards.
*/
async autoLockEditorGroup(): Promise<void> {
if (!this.panel) {
return;
}
// We don't auto-lock anymore to allow multiple Qwen Code tabs in the same group
console.log(
'[PanelManager] Skipping auto-lock to allow multiple Qwen Code tabs',
);
try {
// The newly created panel is focused (preserveFocus: false), so this
// locks the correct, active editor group.
await vscode.commands.executeCommand('workbench.action.lockEditorGroup');
console.log('[PanelManager] Group locked after panel creation');
} catch (error) {
console.warn('[PanelManager] Failed to lock editor group:', error);
}
}
/**

View File

@@ -23,7 +23,6 @@
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color);
z-index: 1;
}
/* First item connector starts lower */

View File

@@ -0,0 +1,98 @@
/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*
* Execute tool call styles - Enhanced styling with semantic class names
*/
/* Root container for execute tool call output */
.execute-toolcall-card {
border: 0.5px solid var(--app-input-border);
border-radius: 5px;
background: var(--app-tool-background);
margin: 8px 0;
max-width: 100%;
font-size: 1em;
align-items: start;
}
/* Content wrapper inside the card */
.execute-toolcall-content {
display: flex;
flex-direction: column;
gap: 3px;
padding: 4px;
}
/* Individual input/output row */
.execute-toolcall-row {
display: grid;
grid-template-columns: max-content 1fr;
border-top: 0.5px solid var(--app-input-border);
padding: 4px;
}
/* First row has no top border */
.execute-toolcall-row:first-child {
border-top: none;
}
/* Row label (IN/OUT/ERROR) */
.execute-toolcall-label {
grid-column: 1;
color: var(--app-secondary-foreground);
text-align: left;
opacity: 50%;
padding: 4px 8px 4px 4px;
font-family: var(--app-monospace-font-family);
font-size: 0.85em;
}
/* Row content area */
.execute-toolcall-row-content {
grid-column: 2;
white-space: pre-wrap;
word-break: break-word;
margin: 0;
padding: 4px;
}
/* Truncated content styling */
.execute-toolcall-row-content:not(.execute-toolcall-full) {
max-height: 60px;
mask-image: linear-gradient(to bottom, var(--app-primary-background) 40px, transparent 60px);
overflow: hidden;
}
/* Preformatted content */
.execute-toolcall-pre {
margin-block: 0;
overflow: hidden;
font-family: var(--app-monospace-font-family);
font-size: 0.85em;
}
/* Code content */
.execute-toolcall-code {
margin: 0;
padding: 0;
font-family: var(--app-monospace-font-family);
font-size: 0.85em;
}
/* Output content with subtle styling */
.execute-toolcall-output-subtle {
background-color: var(--app-code-background);
white-space: pre;
overflow-x: auto;
max-width: 100%;
min-width: 0;
width: 100%;
box-sizing: border-box;
}
/* Error content styling */
.execute-toolcall-error-content {
color: #c74e39;
}

View File

@@ -10,6 +10,7 @@ import type React from 'react';
import type { BaseToolCallProps } from './shared/types.js';
import { ToolCallContainer } from './shared/LayoutComponents.js';
import { safeTitle, groupContent } from './shared/utils.js';
import './ExecuteToolCall.css';
/**
* Specialized component for Execute/Bash tool calls
@@ -35,25 +36,30 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
if (errors.length > 0) {
return (
<ToolCallContainer label="Bash" status="error" toolCallId={toolCallId}>
{/* Branch connector summary (Claude-like) */}
<div className="inline-flex text-[var(--app-secondary-foreground)] text-[0.85em] opacity-70 mt-[2px] mb-[2px] flex-row items-start w-full gap-1">
<span className="flex-shrink-0 relative top-[-0.1em]"></span>
<span className="flex-shrink-0 w-full">{commandText}</span>
</div>
<div className="execute-toolcall-error-card bg-[var(--app-input-background)] border border-[var(--app-input-border)] rounded-md p-3 flex flex-col gap-3 max-w-full overflow-x-auto">
<div className="grid grid-cols-[80px_1fr] gap-3">
<div className="text-xs text-[var(--app-secondary-foreground)] font-medium pt-[2px]">
IN
</div>
<div className="text-[var(--app-primary-foreground)] font-mono text-[13px] break-words">
{inputCommand}
{/* Error card - semantic DOM + Tailwind styles */}
<div className="execute-toolcall-card">
<div className="execute-toolcall-content">
{/* IN row */}
<div className="execute-toolcall-row">
<div className="execute-toolcall-label">IN</div>
<div className="execute-toolcall-row-content">
<pre className="execute-toolcall-pre">{inputCommand}</pre>
</div>
</div>
<div className="grid grid-cols-[80px_1fr] gap-3">
<div className="text-xs text-[var(--app-secondary-foreground)] font-medium pt-[2px]">
Error
</div>
<div className="text-[#c74e39] font-mono text-[13px] whitespace-pre-wrap break-words">
{/* ERROR row */}
<div className="execute-toolcall-row">
<div className="execute-toolcall-label">Error</div>
<div className="execute-toolcall-row-content">
<pre className="execute-toolcall-pre execute-toolcall-error-content">
{errors.join('\n')}
</pre>
</div>
</div>
</div>
</div>
@@ -69,25 +75,30 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
return (
<ToolCallContainer label="Bash" status="success" toolCallId={toolCallId}>
{/* Branch connector summary (Claude-like) */}
<div className="inline-flex text-[var(--app-secondary-foreground)] text-[0.85em] opacity-70 mt-[2px] mb-[2px] flex-row items-start w-full gap-1">
<span className="flex-shrink-0 relative top-[-0.1em]"></span>
<span className="flex-shrink-0 w-full">{commandText}</span>
</div>
<div className="execute-toolcall-output-card bg-[var(--app-input-background)] border border-[var(--app-input-border)] rounded-md p-3 flex flex-col gap-3 max-w-full overflow-x-auto">
<div className="grid grid-cols-[80px_1fr] gap-3">
<div className="text-xs text-[var(--app-secondary-foreground)] font-medium pt-[2px]">
IN
</div>
<div className="text-[var(--app-primary-foreground)] font-mono text-[13px] break-words">
{inputCommand}
{/* Output card - semantic DOM + Tailwind styles */}
<div className="execute-toolcall-card">
<div className="execute-toolcall-content">
{/* IN row */}
<div className="execute-toolcall-row">
<div className="execute-toolcall-label">IN</div>
<div className="execute-toolcall-row-content">
<pre className="execute-toolcall-pre">{inputCommand}</pre>
</div>
</div>
<div className="grid grid-cols-[80px_1fr] gap-3">
<div className="text-xs text-[var(--app-secondary-foreground)] font-medium pt-[2px]">
OUT
{/* OUT row */}
<div className="execute-toolcall-row">
<div className="execute-toolcall-label">OUT</div>
<div className="execute-toolcall-row-content">
<div className="execute-toolcall-output-subtle">
<pre className="execute-toolcall-pre">{truncatedOutput}</pre>
</div>
</div>
<div className="text-[var(--app-primary-foreground)] font-mono text-[13px] whitespace-pre-wrap opacity-90 break-words">
{truncatedOutput}
</div>
</div>
</div>

View File

@@ -25,7 +25,6 @@
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color);
z-index: 1;
}
/* First item: connector starts from status point position */
@@ -156,5 +155,6 @@
/* Flex container with margin bottom */
.toolcall-header {
margin-bottom: 12px;
/* TODO: 应该不需要? 待删除 */
/* margin-bottom: 12px; */
}

View File

@@ -23,7 +23,6 @@
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color);
z-index: 1;
}
/* First item connector starts lower */