✨ feat(vscode): 实施和审查会话行加启动箭头

不用再把卡片拖到「实施中」「审查」列:

- 实施会话id 行在有计划文件且没实施会话时显示 ▶,等同拖进实施中列
- 审查会话id 行在有 PR 时显示 ▶,按 PR 事件那套流程起 codex 审查

Claude-Session: https://claude.ai/code/session_01Kgmb1LvrPmFX3NoUDB4zZC
This commit is contained in:
cruldra committed 2026-09-13 10:52:14 +08:00
1 parent 620b7c73c8
commit 410a04da77
9 files changed
+101 -8

No files matched your search

@@ -31,6 +31,7 @@ interface BottomTabsProps {
onResumeSession: (sessionId: string, kind: 'implement' | 'brainstorm', profilePath?: string, cwd?: string, issueNumber?: number) => void
isSessionTabPending: (sessionId: string) => boolean
onResumeReviewSession: (sessionId: string, issueNumber: number, cwd?: string) => void
onStartReviewSession: (issueNumber: number) => void
onStartTestSession: (issueNumber: number) => void
onResumeTestSession: (sessionId: string, issueNumber: number, cwd?: string) => void
onOpenFile: (path: string) => void
@@ -130,6 +131,7 @@ export function BottomTabs(props: BottomTabsProps) {
onResumeSession={props.onResumeSession}
isSessionTabPending={props.isSessionTabPending}
onResumeReviewSession={props.onResumeReviewSession}
onStartReviewSession={props.onStartReviewSession}
onStartTestSession={props.onStartTestSession}
onResumeTestSession={props.onResumeTestSession}
onOpenFile={props.onOpenFile}
@@ -55,6 +55,7 @@ interface IssueDetailPanelProps {
* Spawn a fresh "测试" cc tab for an issue whose PR has merged. Bound to the
* Play button next to the "测试会话 id" row (only shown when `issue.pr` exists).
*/
onStartReviewSession: (issueNumber: number) => void
onStartTestSession: (issueNumber: number) => void
/** Open a workspace-relative file in the editor. */
onOpenFile: (path: string) => void
@@ -133,6 +134,7 @@ export function IssueDetailPanel({
onResumeSession,
onResumeReviewSession,
onResumeTestSession,
onStartReviewSession,
onStartTestSession,
onOpenFile,
onImplement,
@@ -290,13 +292,27 @@ export function IssueDetailPanel({
return
onResumeSession(v, 'implement', issue?.profilePath, issue?.worktreePath, issue?.number)
},
secondaryActions: issue?.implementTabOpen
? [{
secondaryActions: (() => {
if (issue?.implementTabOpen) {
return [{
icon: <X className="size-3.5" />,
title: '关闭实施 tab',
onClick: () => onCloseSessionTab(issue.number, 'implement'),
}]
: [],
}
// 还没实施会话时给个 ▶,省去把卡片拖进「实施中」列。
if (issue?.implementSessionId || !issue?.planFile)
return []
return [{
icon: <Play className="size-3.5" />,
title: locked ? lockTitle : '启动实施会话',
disabled:
issue.implementStatus === 'running'
|| issue.implementStatus === 'done'
|| locked,
onClick: () => onImplement(issue.number, issue.planFile ?? '', issue.profilePath, issue.sessionId),
}]
})(),
},
issue?.reviewSessionFileExists
? {
@@ -324,9 +340,19 @@ export function IssueDetailPanel({
: {
key: 'reviewSessionId',
label: '审查会话id',
type: 'string',
type: 'action',
readOnly: true,
description: '本机没有该 codex 会话文件,无法 resume;仅保留 id 文本',
description: issue?.reviewSessionId
? '本机没有该 codex 会话文件,无法 resume;点 ▶ 对当前 PR 重新起一个审查会话'
: '还没有审查会话;点 ▶ 对当前 PR 启动 codex 审查(等同 PR 事件自动触发的那次)',
secondaryActions: issue?.pr
? [{
icon: <Play className="size-3.5" />,
title: locked ? lockTitle : '启动审查会话',
disabled: locked,
onClick: () => onStartReviewSession(issue.number),
}]
: [],
},
(() => {
// 测试会话 id 行有三种状态(照搬头脑风暴行的三态):
@@ -542,7 +568,7 @@ export function IssueDetailPanel({
],
},
],
[onResumeSession, onResumeReviewSession, onResumeTestSession, onStartTestSession, onOpenFile, onImplement, onOpenPr, onGeneratePrDiffSummary, onOpenWorktree, onDeleteWorktree, onMergeBranch, onCloseSessionTab, onContinueBrainstorm, onClearBrainstormSession, onOpenLogs, issue, locked, lockTitle, globalAutoReview, prDiffSummaryRunning, profiles, isSessionTabPending],
[onResumeSession, onResumeReviewSession, onResumeTestSession, onStartTestSession, onOpenFile, onImplement, onOpenPr, onGeneratePrDiffSummary, onOpenWorktree, onDeleteWorktree, onMergeBranch, onCloseSessionTab, onContinueBrainstorm, onClearBrainstormSession, onOpenLogs, issue, locked, lockTitle, globalAutoReview, prDiffSummaryRunning, profiles, isSessionTabPending, onStartReviewSession],
)
// 同事的工单只读:属性表统一消毒,顶部只留查看类按钮。