refactor: 清理 P1 类型债与 React key 债
- 消除 useChat.ts 中 13 处 (message as any).timestamp,改用已收窄变量的 .timestamp
- 给 ExecutionCancelled 接口补 timestamp?: number 字段,与后端对齐
- 修复 MessageInput 附件列表 key={index}: 给 FileAttachment 加 id 字段(crypto.randomUUID())
- 修复 ConfigPage TagEditor key={i} → key={t}(tag 值唯一)
- 修复 ConfigPage SourceEditor customPaths key={i} → key={p}(路径值唯一)
This commit is contained in:
parent
7eb2933ca5
commit
f8d5f0253a
@ -16,6 +16,7 @@ interface MessageInputProps {
|
||||
}
|
||||
|
||||
interface FileAttachment {
|
||||
id: string
|
||||
file: File
|
||||
attachment: Attachment
|
||||
preview?: string // 用于图片预览
|
||||
@ -92,6 +93,7 @@ export function MessageInput({
|
||||
}
|
||||
|
||||
const fileAttachment: FileAttachment = {
|
||||
id: crypto.randomUUID(),
|
||||
file,
|
||||
attachment,
|
||||
preview: mediaType === 'image' ? base64 : undefined,
|
||||
@ -170,6 +172,7 @@ export function MessageInput({
|
||||
}
|
||||
|
||||
const fileAttachment: FileAttachment = {
|
||||
id: crypto.randomUUID(),
|
||||
file,
|
||||
attachment,
|
||||
preview: mediaType === 'image' ? base64 : undefined,
|
||||
@ -295,7 +298,7 @@ export function MessageInput({
|
||||
<div className="mb-2 flex flex-wrap gap-2">
|
||||
{attachments.map((att, index) => (
|
||||
<div
|
||||
key={index}
|
||||
key={att.id}
|
||||
className="flex items-center gap-2 rounded-lg border border-[var(--border-color)] bg-[var(--bg-tertiary)] px-2 py-1.5 text-sm"
|
||||
>
|
||||
{att.preview ? (
|
||||
|
||||
@ -192,7 +192,7 @@ function TagEditor({ tags, onChange }: { tags: string[]; onChange: (t: string[])
|
||||
<div className="space-y-2">
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{tags.map((t, i) => (
|
||||
<span key={i} className="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-[var(--accent-cyan)]/10 border border-[var(--accent-cyan)]/20 text-xs text-[var(--accent-cyan)]">
|
||||
<span key={t} className="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-[var(--accent-cyan)]/10 border border-[var(--accent-cyan)]/20 text-xs text-[var(--accent-cyan)]">
|
||||
{t}
|
||||
<button onClick={() => onChange(tags.filter((_, j) => j !== i))} className="hover:text-white transition-colors"><X className="h-3 w-3" /></button>
|
||||
</span>
|
||||
@ -286,8 +286,8 @@ function SourceEditor({
|
||||
<div className="text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">自定义路径</div>
|
||||
{customPaths.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{customPaths.map((p, i) => (
|
||||
<span key={i} className="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-[var(--accent-cyan)]/10 border border-[var(--accent-cyan)]/20 text-xs text-[var(--accent-cyan)] font-mono">
|
||||
{customPaths.map((p) => (
|
||||
<span key={p} className="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-[var(--accent-cyan)]/10 border border-[var(--accent-cyan)]/20 text-xs text-[var(--accent-cyan)] font-mono">
|
||||
{p}
|
||||
<button onClick={() => removeCustom(p)} className="hover:text-white transition-colors"><X className="h-3 w-3" /></button>
|
||||
</span>
|
||||
|
||||
@ -236,7 +236,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role: role as ChatMessage['role'],
|
||||
content: msg.content,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'message',
|
||||
attachments: msg.attachments,
|
||||
subagentTaskId: msg.subagent_task_id,
|
||||
@ -249,7 +249,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role: 'tool',
|
||||
content: msg.content,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'tool_call',
|
||||
toolName: msg.tool_name,
|
||||
toolCallId: msg.tool_call_id,
|
||||
@ -264,7 +264,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role: 'tool',
|
||||
content: msg.content,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'tool_result',
|
||||
toolName: msg.tool_name,
|
||||
toolCallId: msg.tool_call_id,
|
||||
@ -278,7 +278,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role: 'tool',
|
||||
content: `${msg.content}\n\n${msg.resume_hint}`,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'tool_pending',
|
||||
toolName: msg.tool_name,
|
||||
toolCallId: msg.tool_call_id,
|
||||
@ -302,7 +302,7 @@ export function useChat(): UseChatReturn {
|
||||
id: generateMessageId(),
|
||||
role: 'assistant',
|
||||
content: `Error: ${message.message}`,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: message.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'message',
|
||||
}
|
||||
}
|
||||
@ -362,7 +362,7 @@ export function useChat(): UseChatReturn {
|
||||
id: generateMessageId(),
|
||||
role: 'assistant',
|
||||
content: `Error: ${errMsg.message}`,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: errMsg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'message',
|
||||
}
|
||||
setSubAgentStack((prev) => {
|
||||
@ -423,7 +423,7 @@ export function useChat(): UseChatReturn {
|
||||
id: generateMessageId(),
|
||||
role: 'assistant',
|
||||
content: `Error: ${errMsg.message}`,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: errMsg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'message',
|
||||
}
|
||||
const newStack = [...prev]
|
||||
@ -800,7 +800,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role,
|
||||
content: msg.content,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'message',
|
||||
attachments: msg.attachments,
|
||||
reasoningContent: msg.reasoning_content,
|
||||
@ -833,7 +833,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role: 'tool',
|
||||
content: msg.content,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'tool_call',
|
||||
toolName: msg.tool_name,
|
||||
toolCallId: msg.tool_call_id,
|
||||
@ -856,7 +856,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role: 'tool',
|
||||
content: msg.content,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'tool_result',
|
||||
toolName: msg.tool_name,
|
||||
toolCallId: msg.tool_call_id,
|
||||
@ -877,7 +877,7 @@ export function useChat(): UseChatReturn {
|
||||
id: msg.id,
|
||||
role: 'tool',
|
||||
content: `${msg.content}\n\n${msg.resume_hint}`,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: msg.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'tool_pending',
|
||||
toolName: msg.tool_name,
|
||||
toolCallId: msg.tool_call_id,
|
||||
@ -893,7 +893,7 @@ export function useChat(): UseChatReturn {
|
||||
id: generateMessageId(),
|
||||
role: 'assistant',
|
||||
content: (message as { type: 'execution_cancelled'; message: string }).message,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: message.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'message',
|
||||
},
|
||||
])
|
||||
@ -910,7 +910,7 @@ export function useChat(): UseChatReturn {
|
||||
id: generateMessageId(),
|
||||
role: 'assistant',
|
||||
content: `Error: ${message.message}`,
|
||||
timestamp: (message as any).timestamp ?? Math.floor(Date.now() / 1000),
|
||||
timestamp: message.timestamp ?? Math.floor(Date.now() / 1000),
|
||||
type: 'message',
|
||||
},
|
||||
])
|
||||
|
||||
@ -260,6 +260,7 @@ export interface TaskMessagesLoaded {
|
||||
export interface ExecutionCancelled {
|
||||
type: 'execution_cancelled'
|
||||
message: string
|
||||
timestamp?: number
|
||||
}
|
||||
|
||||
export interface StreamDelta {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user