[moz] feat(frontend): 工具链面板加 from/to 显示 + 筛选 + 修复事件类型未知
- 前端:列表项加 from → to 标签(Agent 中文名) - 前端:加「全部 / 未处理」筛选按钮 - 前端:详情区也显示 from → to - 后端:ToolchainContextSection 修复事件类型 fallback 为中文标签 - 后端:加来源/指派信息到 prompt 消息体
This commit is contained in:
@@ -51,17 +51,41 @@ class ToolchainContextSection:
|
|||||||
name: str = "toolchain_context"
|
name: str = "toolchain_context"
|
||||||
priority: int = 10
|
priority: int = 10
|
||||||
|
|
||||||
|
EVENT_LABELS_ZH: Dict[str, str] = {
|
||||||
|
"review_request": "Review 请求",
|
||||||
|
"review_result": "Review 结果",
|
||||||
|
"review_merged": "PR 合并",
|
||||||
|
"review_comment": "Review 评论",
|
||||||
|
"review_updated": "Review 更新",
|
||||||
|
"ci_failure": "CI 失败",
|
||||||
|
"deploy_failure": "部署失败",
|
||||||
|
"issue_assigned": "Issue 指派",
|
||||||
|
"mention": "@提及",
|
||||||
|
}
|
||||||
|
|
||||||
def render(self, context: PromptContext) -> str:
|
def render(self, context: PromptContext) -> str:
|
||||||
event_type = context.event_type
|
event_type = context.event_type
|
||||||
event_data: Dict = context.event_data or {}
|
event_data: Dict = context.event_data or {}
|
||||||
|
|
||||||
|
# 事件类型中文标签
|
||||||
|
event_label = self.EVENT_LABELS_ZH.get(event_type, event_type or '未知')
|
||||||
|
|
||||||
|
# from / to 信息
|
||||||
|
to_agent = context.agent_id or ''
|
||||||
|
from_agent = 'system'
|
||||||
|
|
||||||
# Part 1: 事件信息(现有模板引擎)
|
# Part 1: 事件信息(现有模板引擎)
|
||||||
if event_type in _TEMPLATE_MAP:
|
if event_type in _TEMPLATE_MAP:
|
||||||
variables = {k: str(v) for k, v in event_data.items()}
|
variables = {k: str(v) for k, v in event_data.items()}
|
||||||
event_text = render_template(event_type, variables)
|
event_text = render_template(event_type, variables)
|
||||||
|
# 补充事件类型中文标签 + from/to
|
||||||
|
header = f"- **事件类型**: {event_label}\n- **来源**: {from_agent}\n- **指派**: {to_agent}\n"
|
||||||
|
event_text = header + "\n" + event_text
|
||||||
else:
|
else:
|
||||||
lines = ["## 工具链事件", ""]
|
lines = ["## 工具链事件", ""]
|
||||||
lines.append(f"- **事件类型**: {event_type or '未知'}")
|
lines.append(f"- **事件类型**: {event_label}")
|
||||||
|
lines.append(f"- **来源**: {from_agent}")
|
||||||
|
lines.append(f"- **指派**: {to_agent}")
|
||||||
if event_data:
|
if event_data:
|
||||||
lines.append("- **事件详情**:")
|
lines.append("- **事件详情**:")
|
||||||
for key, value in event_data.items():
|
for key, value in event_data.items():
|
||||||
|
|||||||
@@ -4,6 +4,28 @@
|
|||||||
*/
|
*/
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
const AGENT_NAMES: Record<string, string> = {
|
||||||
|
'pangtong-fujunshi': '庞统',
|
||||||
|
'simayi-challenger': '司马懿',
|
||||||
|
'zhangfei-dev': '张飞',
|
||||||
|
'guanyu-dev': '关羽',
|
||||||
|
'zhaoyun-data': '赵云',
|
||||||
|
'jiangwei-infra': '姜维',
|
||||||
|
'system': '系统',
|
||||||
|
};
|
||||||
|
|
||||||
|
const EVENT_LABELS: Record<string, string> = {
|
||||||
|
'review_request': 'Review 请求',
|
||||||
|
'review_result': 'Review 结果',
|
||||||
|
'review_merged': 'PR 合并',
|
||||||
|
'review_comment': 'Review 评论',
|
||||||
|
'review_updated': 'Review 更新',
|
||||||
|
'ci_failure': 'CI 失败',
|
||||||
|
'deploy_failure': '部署失败',
|
||||||
|
'issue_assigned': 'Issue 指派',
|
||||||
|
'mention': '@提及',
|
||||||
|
};
|
||||||
|
|
||||||
const STATUS_COLORS: Record<string, string> = {
|
const STATUS_COLORS: Record<string, string> = {
|
||||||
pending: '#f59e0b22', claimed: '#6a9eff22', working: '#6a9eff22',
|
pending: '#f59e0b22', claimed: '#6a9eff22', working: '#6a9eff22',
|
||||||
review: '#818cf822', done: '#2ecc8a22', failed: '#ef444422',
|
review: '#818cf822', done: '#2ecc8a22', failed: '#ef444422',
|
||||||
@@ -36,6 +58,7 @@ export default function ToolchainPanel() {
|
|||||||
const [detail, setDetail] = useState<any>(null);
|
const [detail, setDetail] = useState<any>(null);
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [filterMode, setFilterMode] = useState<'all' | 'pending'>('all');
|
||||||
|
|
||||||
const loadTasks = async (q?: string) => {
|
const loadTasks = async (q?: string) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -52,6 +75,10 @@ export default function ToolchainPanel() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const displayed = filterMode === 'pending'
|
||||||
|
? tasks.filter(t => !['done', 'failed', 'cancelled'].includes(t.status))
|
||||||
|
: tasks;
|
||||||
|
|
||||||
useEffect(() => { loadTasks(); }, []);
|
useEffect(() => { loadTasks(); }, []);
|
||||||
|
|
||||||
// 搜索防抖 300ms
|
// 搜索防抖 300ms
|
||||||
@@ -120,7 +147,19 @@ export default function ToolchainPanel() {
|
|||||||
padding: '3px 8px', borderRadius: 4, fontSize: 10,
|
padding: '3px 8px', borderRadius: 4, fontSize: 10,
|
||||||
border: '1px solid #2a3550', background: '#161b2e', color: '#8899aa', cursor: 'pointer',
|
border: '1px solid #2a3550', background: '#161b2e', color: '#8899aa', cursor: 'pointer',
|
||||||
}}>🔄</button>
|
}}>🔄</button>
|
||||||
<span style={{ fontSize: 10, color: 'var(--muted)' }}>{tasks.length} 条</span>
|
<button onClick={() => setFilterMode('all')} style={{
|
||||||
|
padding: '3px 8px', borderRadius: 4, fontSize: 10,
|
||||||
|
border: `1px solid ${filterMode === 'all' ? 'var(--acc)' : '#2a3550'}`,
|
||||||
|
background: filterMode === 'all' ? 'var(--acc)22' : '#161b2e',
|
||||||
|
color: filterMode === 'all' ? 'var(--acc)' : '#8899aa', cursor: 'pointer',
|
||||||
|
}}>全部</button>
|
||||||
|
<button onClick={() => setFilterMode('pending')} style={{
|
||||||
|
padding: '3px 8px', borderRadius: 4, fontSize: 10,
|
||||||
|
border: `1px solid ${filterMode === 'pending' ? 'var(--acc)' : '#2a3550'}`,
|
||||||
|
background: filterMode === 'pending' ? 'var(--acc)22' : '#161b2e',
|
||||||
|
color: filterMode === 'pending' ? 'var(--acc)' : '#8899aa', cursor: 'pointer',
|
||||||
|
}}>未处理</button>
|
||||||
|
<span style={{ fontSize: 10, color: 'var(--muted)' }}>{filterMode === 'pending' ? displayed.length : tasks.length} 条</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 事件列表 */}
|
{/* 事件列表 */}
|
||||||
@@ -130,7 +169,7 @@ export default function ToolchainPanel() {
|
|||||||
{loading ? '加载中...' : '暂无工具链事件'}
|
{loading ? '加载中...' : '暂无工具链事件'}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{tasks.map((t: any) => (
|
{displayed.map((t: any) => (
|
||||||
<div key={t.id} onClick={() => setSelectedId(t.id)} style={{
|
<div key={t.id} onClick={() => setSelectedId(t.id)} style={{
|
||||||
padding: '10px 14px', borderBottom: '1px solid var(--line)',
|
padding: '10px 14px', borderBottom: '1px solid var(--line)',
|
||||||
cursor: 'pointer', transition: 'background .15s',
|
cursor: 'pointer', transition: 'background .15s',
|
||||||
@@ -151,6 +190,9 @@ export default function ToolchainPanel() {
|
|||||||
fontSize: 12, fontWeight: 500, color: '#dde4f8',
|
fontSize: 12, fontWeight: 500, color: '#dde4f8',
|
||||||
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||||||
}}>{t.title}</div>
|
}}>{t.title}</div>
|
||||||
|
<div style={{ fontSize: 10, color: 'var(--muted)', marginTop: 2 }}>
|
||||||
|
{AGENT_NAMES['system'] || '系统'} → {AGENT_NAMES[t.assignee] || t.assignee || '?'}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -174,6 +216,9 @@ export default function ToolchainPanel() {
|
|||||||
<span style={{ fontSize: 10, color: 'var(--muted)' }}>{detail.id}</span>
|
<span style={{ fontSize: 10, color: 'var(--muted)' }}>{detail.id}</span>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: 18, fontWeight: 700, lineHeight: 1.3 }}>{detail.title}</div>
|
<div style={{ fontSize: 18, fontWeight: 700, lineHeight: 1.3 }}>{detail.title}</div>
|
||||||
|
<div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 4 }}>
|
||||||
|
{AGENT_NAMES['system'] || '系统'} → {AGENT_NAMES[detail.assignee] || detail.assignee || '?'}
|
||||||
|
</div>
|
||||||
<div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 6 }}>
|
<div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 6 }}>
|
||||||
{fmtTime(detail.created_at)}
|
{fmtTime(detail.created_at)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user