mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-21 09:17:53 +00:00
fix(vscode-ide-companion): improve message logging and permission handling
- Increase message logging truncation limit from 500 to 1500 characters - Fix permission option mapping logic for reject_once/cancel options - Add TODO comments for diff accept/cancel responses during permission requests Resolves issues with permission handling and improves debugging capabilities.
This commit is contained in:
@@ -53,10 +53,27 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Map tool status to container status for proper bullet coloring
|
||||
const containerStatus:
|
||||
| 'success'
|
||||
| 'error'
|
||||
| 'warning'
|
||||
| 'loading'
|
||||
| 'default' =
|
||||
errors.length > 0
|
||||
? 'error'
|
||||
: toolCall.status === 'in_progress' || toolCall.status === 'pending'
|
||||
? 'loading'
|
||||
: 'success';
|
||||
|
||||
// Error case
|
||||
if (errors.length > 0) {
|
||||
return (
|
||||
<ToolCallContainer label="Bash" status="error" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label="Bash"
|
||||
status={containerStatus}
|
||||
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>
|
||||
@@ -99,7 +116,11 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
output.length > 500 ? output.substring(0, 500) + '...' : output;
|
||||
|
||||
return (
|
||||
<ToolCallContainer label="Bash" status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label="Bash"
|
||||
status={containerStatus}
|
||||
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>
|
||||
@@ -141,7 +162,11 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
|
||||
// Success without output: show command with branch connector
|
||||
return (
|
||||
<ToolCallContainer label="Bash" status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label="Bash"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
<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"
|
||||
onClick={handleInClick}
|
||||
|
||||
@@ -9,10 +9,13 @@
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import type { BaseToolCallProps } from '../shared/types.js';
|
||||
import { ToolCallContainer } from '../shared/LayoutComponents.js';
|
||||
import { DiffDisplay } from '../shared/DiffDisplay.js';
|
||||
import { groupContent } from '../shared/utils.js';
|
||||
import {
|
||||
groupContent,
|
||||
mapToolStatusToContainerStatus,
|
||||
} from '../shared/utils.js';
|
||||
import { useVSCode } from '../../../hooks/useVSCode.js';
|
||||
import { FileLink } from '../../ui/FileLink.js';
|
||||
import { isDevelopmentMode } from '../../../utils/envUtils.js';
|
||||
|
||||
/**
|
||||
* Calculate diff summary (added/removed lines)
|
||||
@@ -65,6 +68,7 @@ export const EditToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
const getFileName = (path: string): string => path.split('/').pop() || path;
|
||||
|
||||
// Automatically trigger openDiff when diff content is detected (Claude Code style)
|
||||
// Only trigger once per tool call by checking toolCallId
|
||||
useEffect(() => {
|
||||
// Only auto-open if there are diffs and we have the required data
|
||||
if (diffs.length > 0) {
|
||||
@@ -76,16 +80,16 @@ export const EditToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
firstDiff.oldText !== undefined &&
|
||||
firstDiff.newText !== undefined
|
||||
) {
|
||||
// TODO: 暂时注释
|
||||
// TODO: 暂时注释自动打开功能,避免频繁触发
|
||||
// Add a small delay to ensure the component is fully rendered
|
||||
// const timer = setTimeout(() => {
|
||||
// handleOpenDiff(path, firstDiff.oldText, firstDiff.newText);
|
||||
// }, 100);
|
||||
let timer;
|
||||
const timer = setTimeout(() => {
|
||||
handleOpenDiff(path, firstDiff.oldText, firstDiff.newText);
|
||||
}, 100);
|
||||
// Proper cleanup function
|
||||
return () => timer && clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
}, [diffs, locations, handleOpenDiff]);
|
||||
}, [diffs, handleOpenDiff, locations]); // Add missing dependencies
|
||||
|
||||
// Error case: show error
|
||||
if (errors.length > 0) {
|
||||
@@ -121,15 +125,15 @@ export const EditToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
const openFirstDiff = () =>
|
||||
handleOpenDiff(path, firstDiff.oldText, firstDiff.newText);
|
||||
|
||||
const containerStatus = mapToolStatusToContainerStatus(toolCall.status);
|
||||
return (
|
||||
<div
|
||||
className="qwen-message message-item relative py-2 select-text cursor-pointer hover:bg-[var(--app-input-background)] toolcall-container toolcall-status-success"
|
||||
className={`qwen-message message-item relative py-2 select-text cursor-pointer hover:bg-[var(--app-input-background)] toolcall-container toolcall-status-${containerStatus}`}
|
||||
onClick={openFirstDiff}
|
||||
title="Open diff in VS Code"
|
||||
>
|
||||
{/* Keep content within overall width: pl-[30px] provides the bullet indent; */}
|
||||
{/* IMPORTANT: Always include min-w-0/max-w-full on inner wrappers to prevent overflow. */}
|
||||
<div className="toolcall-edit-content flex flex-col gap-1 min-w-0 max-w-full pl-[30px]">
|
||||
<div className="toolcall-edit-content flex flex-col gap-1 min-w-0 max-w-full">
|
||||
<div className="flex items-center justify-between min-w-0">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
{/* Align the inline Edit label styling with shared toolcall label: larger + bold */}
|
||||
@@ -143,38 +147,18 @@ export const EditToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
className="text-xs font-mono text-[var(--app-secondary-foreground)] hover:underline"
|
||||
/>
|
||||
)}
|
||||
{/* {toolCallId && (
|
||||
<span className="text-[10px] opacity-30">
|
||||
[{toolCallId.slice(-8)}]
|
||||
</span>
|
||||
)} */}
|
||||
</div>
|
||||
<span className="text-xs opacity-60 ml-2">open</span>
|
||||
</div>
|
||||
<div className="inline-flex text-[var(--app-secondary-foreground)] text-[0.85em] opacity-70 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">{summary}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content area aligned with bullet indent. Do NOT exceed container width. */}
|
||||
{/* For any custom blocks here, keep: min-w-0 max-w-full and avoid extra horizontal padding/margins. */}
|
||||
<div className="pl-[30px] mt-1 min-w-0 max-w-full overflow-hidden">
|
||||
{diffs.map(
|
||||
(
|
||||
item: import('../shared/types.js').ToolCallContent,
|
||||
idx: number,
|
||||
) => (
|
||||
<DiffDisplay
|
||||
key={`diff-${idx}`}
|
||||
path={item.path}
|
||||
oldText={item.oldText}
|
||||
newText={item.newText}
|
||||
onOpenDiff={() =>
|
||||
handleOpenDiff(item.path, item.oldText, item.newText)
|
||||
}
|
||||
/>
|
||||
),
|
||||
{/* Show toolCallId only in development/debug mode */}
|
||||
{toolCallId && isDevelopmentMode() && (
|
||||
<span className="text-[10px] opacity-30">
|
||||
[{toolCallId.slice(-8)}]
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -184,10 +168,11 @@ export const EditToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
// Success case without diff: show file in compact format
|
||||
if (locations && locations.length > 0) {
|
||||
const fileName = getFileName(locations[0].path);
|
||||
const containerStatus = mapToolStatusToContainerStatus(toolCall.status);
|
||||
return (
|
||||
<ToolCallContainer
|
||||
label={`Edited ${fileName}`}
|
||||
status="success"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
<div className="inline-flex text-[var(--app-secondary-foreground)] text-[0.85em] opacity-70 flex-row items-start w-full gap-1">
|
||||
|
||||
@@ -32,12 +32,25 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
inputCommand = rawInput;
|
||||
}
|
||||
|
||||
// Map tool status to container status for proper bullet coloring
|
||||
const containerStatus:
|
||||
| 'success'
|
||||
| 'error'
|
||||
| 'warning'
|
||||
| 'loading'
|
||||
| 'default' =
|
||||
errors.length > 0 || toolCall.status === 'failed'
|
||||
? 'error'
|
||||
: toolCall.status === 'in_progress' || toolCall.status === 'pending'
|
||||
? 'loading'
|
||||
: 'success';
|
||||
|
||||
// Error case
|
||||
if (errors.length > 0) {
|
||||
return (
|
||||
<ToolCallContainer
|
||||
label="Execute"
|
||||
status="error"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
className="execute-default-toolcall"
|
||||
>
|
||||
@@ -81,7 +94,7 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
return (
|
||||
<ToolCallContainer
|
||||
label="Execute"
|
||||
status="success"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
{/* Branch connector summary (Claude-like) */}
|
||||
@@ -117,7 +130,11 @@ export const ExecuteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
|
||||
// Success without output: show command with branch connector
|
||||
return (
|
||||
<ToolCallContainer label="Execute" status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label="Execute"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
<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>
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
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 {
|
||||
safeTitle,
|
||||
groupContent,
|
||||
mapToolStatusToContainerStatus,
|
||||
} from '../shared/utils.js';
|
||||
import './ExecuteNode.css';
|
||||
|
||||
/**
|
||||
@@ -60,7 +64,11 @@ export const ExecuteNodeToolCall: React.FC<BaseToolCallProps> = ({
|
||||
|
||||
// Success case: show command with branch connector (similar to the example)
|
||||
return (
|
||||
<ToolCallContainer label="Execute" status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label="Execute"
|
||||
status={mapToolStatusToContainerStatus(toolCall.status)}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
<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>
|
||||
|
||||
@@ -104,8 +104,16 @@ export const GenericToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
}
|
||||
|
||||
// Short output - compact format
|
||||
const statusFlag: 'success' | 'error' | 'warning' | 'loading' | 'default' =
|
||||
toolCall.status === 'in_progress' || toolCall.status === 'pending'
|
||||
? 'loading'
|
||||
: 'success';
|
||||
return (
|
||||
<ToolCallContainer label={kind} status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label={kind}
|
||||
status={statusFlag}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
{operationText || output}
|
||||
</ToolCallContainer>
|
||||
);
|
||||
@@ -113,8 +121,16 @@ export const GenericToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
|
||||
// Success with files: show operation + file list in compact format
|
||||
if (locations && locations.length > 0) {
|
||||
const statusFlag: 'success' | 'error' | 'warning' | 'loading' | 'default' =
|
||||
toolCall.status === 'in_progress' || toolCall.status === 'pending'
|
||||
? 'loading'
|
||||
: 'success';
|
||||
return (
|
||||
<ToolCallContainer label={kind} status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label={kind}
|
||||
status={statusFlag}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
<LocationsList locations={locations} />
|
||||
</ToolCallContainer>
|
||||
);
|
||||
@@ -122,8 +138,16 @@ export const GenericToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
|
||||
// No output - show just the operation
|
||||
if (operationText) {
|
||||
const statusFlag: 'success' | 'error' | 'warning' | 'loading' | 'default' =
|
||||
toolCall.status === 'in_progress' || toolCall.status === 'pending'
|
||||
? 'loading'
|
||||
: 'success';
|
||||
return (
|
||||
<ToolCallContainer label={kind} status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label={kind}
|
||||
status={statusFlag}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
{operationText}
|
||||
</ToolCallContainer>
|
||||
);
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
import type React from 'react';
|
||||
import type { BaseToolCallProps } from '../shared/types.js';
|
||||
import { ToolCallContainer } from '../shared/LayoutComponents.js';
|
||||
import { groupContent } from '../shared/utils.js';
|
||||
import {
|
||||
groupContent,
|
||||
mapToolStatusToContainerStatus,
|
||||
} from '../shared/utils.js';
|
||||
import { FileLink } from '../../ui/FileLink.js';
|
||||
|
||||
/**
|
||||
@@ -23,6 +26,14 @@ export const ReadToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
// Group content by type
|
||||
const { errors } = groupContent(content);
|
||||
|
||||
// Compute container status based on toolCall.status (pending/in_progress -> loading)
|
||||
const containerStatus:
|
||||
| 'success'
|
||||
| 'error'
|
||||
| 'warning'
|
||||
| 'loading'
|
||||
| 'default' = mapToolStatusToContainerStatus(toolCall.status);
|
||||
|
||||
// Error case: show error
|
||||
if (errors.length > 0) {
|
||||
const path = locations?.[0]?.path || '';
|
||||
@@ -54,7 +65,7 @@ export const ReadToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
<ToolCallContainer
|
||||
label={'Read'}
|
||||
className="read-tool-call-success"
|
||||
status="success"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
labelSuffix={
|
||||
path ? (
|
||||
|
||||
@@ -7,14 +7,18 @@
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import type { BaseToolCallProps } from './shared/types.js';
|
||||
import type { BaseToolCallProps } from '../shared/types.js';
|
||||
import {
|
||||
ToolCallContainer,
|
||||
ToolCallCard,
|
||||
ToolCallRow,
|
||||
LocationsList,
|
||||
} from './shared/LayoutComponents.js';
|
||||
import { safeTitle, groupContent } from './shared/utils.js';
|
||||
} from '../shared/LayoutComponents.js';
|
||||
import {
|
||||
safeTitle,
|
||||
groupContent,
|
||||
mapToolStatusToContainerStatus,
|
||||
} from '../shared/utils.js';
|
||||
|
||||
/**
|
||||
* Specialized component for Search tool calls
|
||||
@@ -44,6 +48,7 @@ export const SearchToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
|
||||
// Success case with results: show search query + file list
|
||||
if (locations && locations.length > 0) {
|
||||
const containerStatus = mapToolStatusToContainerStatus(toolCall.status);
|
||||
// If multiple results, use card layout; otherwise use compact format
|
||||
if (locations.length > 1) {
|
||||
return (
|
||||
@@ -59,8 +64,13 @@ export const SearchToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
}
|
||||
// Single result - compact format
|
||||
return (
|
||||
<ToolCallContainer label="Search" status="success">
|
||||
<span className="font-mono">{queryText}</span>
|
||||
<ToolCallContainer
|
||||
label="Search"
|
||||
status={containerStatus}
|
||||
className="search-toolcall"
|
||||
labelSuffix={`(${queryText})`}
|
||||
>
|
||||
{/* <span className="font-mono">{queryText}</span> */}
|
||||
<span className="mx-2 opacity-50">→</span>
|
||||
<LocationsList locations={locations} />
|
||||
</ToolCallContainer>
|
||||
@@ -69,8 +79,13 @@ export const SearchToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
|
||||
// No results - show query only
|
||||
if (queryText) {
|
||||
const containerStatus = mapToolStatusToContainerStatus(toolCall.status);
|
||||
return (
|
||||
<ToolCallContainer label="Search" status="success">
|
||||
<ToolCallContainer
|
||||
label="Search"
|
||||
status={containerStatus}
|
||||
className="search-toolcall"
|
||||
>
|
||||
<span className="font-mono">{queryText}</span>
|
||||
</ToolCallContainer>
|
||||
);
|
||||
@@ -7,13 +7,13 @@
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import type { BaseToolCallProps } from './shared/types.js';
|
||||
import type { BaseToolCallProps } from '../shared/types.js';
|
||||
import {
|
||||
ToolCallContainer,
|
||||
ToolCallCard,
|
||||
ToolCallRow,
|
||||
} from './shared/LayoutComponents.js';
|
||||
import { groupContent } from './shared/utils.js';
|
||||
} from '../shared/LayoutComponents.js';
|
||||
import { groupContent } from '../shared/utils.js';
|
||||
|
||||
/**
|
||||
* Specialized component for Think tool calls
|
||||
@@ -56,8 +56,12 @@ export const ThinkToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
}
|
||||
|
||||
// Short thoughts - compact format
|
||||
const status =
|
||||
toolCall.status === 'pending' || toolCall.status === 'in_progress'
|
||||
? 'loading'
|
||||
: 'default';
|
||||
return (
|
||||
<ToolCallContainer label="Thinking" status="default">
|
||||
<ToolCallContainer label="Thinking" status={status}>
|
||||
<span className="italic opacity-90">{thoughts}</span>
|
||||
</ToolCallContainer>
|
||||
);
|
||||
@@ -7,10 +7,10 @@
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import type { BaseToolCallProps } from './shared/types.js';
|
||||
import { ToolCallContainer } from './shared/LayoutComponents.js';
|
||||
import { groupContent, safeTitle } from './shared/utils.js';
|
||||
import { CheckboxDisplay } from '../ui/CheckboxDisplay.js';
|
||||
import type { BaseToolCallProps } from '../shared/types.js';
|
||||
import { ToolCallContainer } from '../shared/LayoutComponents.js';
|
||||
import { groupContent, safeTitle } from '../shared/utils.js';
|
||||
import { CheckboxDisplay } from '../../ui/CheckboxDisplay.js';
|
||||
|
||||
type EntryStatus = 'pending' | 'in_progress' | 'completed';
|
||||
|
||||
@@ -20,7 +20,7 @@ interface TodoEntry {
|
||||
}
|
||||
|
||||
const mapToolStatusToBullet = (
|
||||
status: import('./shared/types.js').ToolCallStatus,
|
||||
status: import('../shared/types.js').ToolCallStatus,
|
||||
): 'success' | 'error' | 'warning' | 'loading' | 'default' => {
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
@@ -7,10 +7,13 @@
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import type { BaseToolCallProps } from './shared/types.js';
|
||||
import { ToolCallContainer } from './shared/LayoutComponents.js';
|
||||
import { groupContent } from './shared/utils.js';
|
||||
import { FileLink } from '../ui/FileLink.js';
|
||||
import type { BaseToolCallProps } from '../shared/types.js';
|
||||
import { ToolCallContainer } from '../shared/LayoutComponents.js';
|
||||
import {
|
||||
groupContent,
|
||||
mapToolStatusToContainerStatus,
|
||||
} from '../shared/utils.js';
|
||||
import { FileLink } from '../../ui/FileLink.js';
|
||||
|
||||
/**
|
||||
* Specialized component for Write tool calls
|
||||
@@ -79,10 +82,11 @@ export const WriteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
if (locations && locations.length > 0) {
|
||||
const path = locations[0].path;
|
||||
const lineCount = writeContent.split('\n').length;
|
||||
const containerStatus = mapToolStatusToContainerStatus(toolCall.status);
|
||||
return (
|
||||
<ToolCallContainer
|
||||
label={'Created'}
|
||||
status="success"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
labelSuffix={
|
||||
path ? (
|
||||
@@ -104,8 +108,13 @@ export const WriteToolCall: React.FC<BaseToolCallProps> = ({ toolCall }) => {
|
||||
|
||||
// Fallback: show generic success
|
||||
if (textOutputs.length > 0) {
|
||||
const containerStatus = mapToolStatusToContainerStatus(toolCall.status);
|
||||
return (
|
||||
<ToolCallContainer label="Write" status="success" toolCallId={toolCallId}>
|
||||
<ToolCallContainer
|
||||
label="Write"
|
||||
status={containerStatus}
|
||||
toolCallId={toolCallId}
|
||||
>
|
||||
{textOutputs.join('\n')}
|
||||
</ToolCallContainer>
|
||||
);
|
||||
@@ -11,15 +11,14 @@ import type { BaseToolCallProps } from './shared/types.js';
|
||||
import { shouldShowToolCall } from './shared/utils.js';
|
||||
import { GenericToolCall } from './GenericToolCall.js';
|
||||
import { ReadToolCall } from './Read/ReadToolCall.js';
|
||||
import { WriteToolCall } from './WriteToolCall.js';
|
||||
import { WriteToolCall } from './Write/WriteToolCall.js';
|
||||
import { EditToolCall } from './Edit/EditToolCall.js';
|
||||
import { ExecuteToolCall as BashExecuteToolCall } from './Bash/Bash.js';
|
||||
import { ExecuteToolCall } from './Execute/Execute.js';
|
||||
import { UpdatedPlanToolCall } from './UpdatedPlan/UpdatedPlanToolCall.js';
|
||||
import { ExecuteNodeToolCall } from './ExecuteNode/ExecuteNodeToolCall.js';
|
||||
import { SearchToolCall } from './SearchToolCall.js';
|
||||
import { ThinkToolCall } from './ThinkToolCall.js';
|
||||
import { TodoWriteToolCall } from './TodoWriteToolCall.js';
|
||||
import { SearchToolCall } from './Search/SearchToolCall.js';
|
||||
import { ThinkToolCall } from './Think/ThinkToolCall.js';
|
||||
|
||||
/**
|
||||
* Factory function that returns the appropriate tool call component based on kind
|
||||
@@ -69,7 +68,10 @@ export const getToolCallComponent = (
|
||||
case 'updated_plan':
|
||||
case 'updatedplan':
|
||||
case 'todo_write':
|
||||
case 'update_todos':
|
||||
case 'todowrite':
|
||||
return UpdatedPlanToolCall;
|
||||
// return TodoWriteToolCall;
|
||||
|
||||
case 'search':
|
||||
case 'grep':
|
||||
@@ -81,18 +83,6 @@ export const getToolCallComponent = (
|
||||
case 'thinking':
|
||||
return ThinkToolCall;
|
||||
|
||||
case 'todowrite':
|
||||
return TodoWriteToolCall;
|
||||
// case 'todo_write':
|
||||
case 'update_todos':
|
||||
return TodoWriteToolCall;
|
||||
|
||||
// Add more specialized components as needed
|
||||
// case 'fetch':
|
||||
// return FetchToolCall;
|
||||
// case 'delete':
|
||||
// return DeleteToolCall;
|
||||
|
||||
default:
|
||||
// Fallback to generic component
|
||||
return GenericToolCall;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
import type React from 'react';
|
||||
import { FileLink } from '../../ui/FileLink.js';
|
||||
import { isDevelopmentMode } from '../../../utils/envUtils.js';
|
||||
import './LayoutComponents.css';
|
||||
|
||||
/**
|
||||
@@ -53,12 +54,6 @@ export const ToolCallContainer: React.FC<ToolCallContainerProps> = ({
|
||||
<span className="text-[14px] leading-none font-bold text-[var(--app-primary-foreground)]">
|
||||
{label}
|
||||
</span>
|
||||
{/* TODO: for 调试 */}
|
||||
{_toolCallId && (
|
||||
<span className="text-[10px] opacity-30">
|
||||
[{_toolCallId.slice(-8)}]
|
||||
</span>
|
||||
)}
|
||||
{labelSuffix}
|
||||
</div>
|
||||
{children && (
|
||||
@@ -66,6 +61,13 @@ export const ToolCallContainer: React.FC<ToolCallContainerProps> = ({
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Show toolCallId only in development/debug mode */}
|
||||
{_toolCallId && isDevelopmentMode() && (
|
||||
<span className="text-[10px] opacity-30">
|
||||
[{_toolCallId.slice(-8)}]
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
* Shared utility functions for tool call components
|
||||
*/
|
||||
|
||||
import type { ToolCallContent, GroupedContent } from './types.js';
|
||||
import type {
|
||||
ToolCallContent,
|
||||
GroupedContent,
|
||||
ToolCallStatus,
|
||||
} from './types.js';
|
||||
|
||||
/**
|
||||
* Format any value to a string for display
|
||||
@@ -194,3 +198,26 @@ export const groupContent = (content?: ToolCallContent[]): GroupedContent => {
|
||||
|
||||
return { textOutputs, errors, diffs, otherData };
|
||||
};
|
||||
|
||||
/**
|
||||
* Map a tool call status to a ToolCallContainer status (bullet color)
|
||||
* - pending/in_progress -> loading
|
||||
* - completed -> success
|
||||
* - failed -> error
|
||||
* - default fallback
|
||||
*/
|
||||
export const mapToolStatusToContainerStatus = (
|
||||
status: ToolCallStatus,
|
||||
): 'success' | 'error' | 'warning' | 'loading' | 'default' => {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
case 'in_progress':
|
||||
return 'loading';
|
||||
case 'failed':
|
||||
return 'error';
|
||||
case 'completed':
|
||||
return 'success';
|
||||
default:
|
||||
return 'default';
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user