mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
refactor(vscode-ide-companion/panel): reimplement editor group locking with proper error handling
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
background-color: var(--app-primary-border-color);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* First item connector starts lower */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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; */
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
background-color: var(--app-primary-border-color);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* First item connector starts lower */
|
||||
|
||||
Reference in New Issue
Block a user