feat(vscode): 审查会话链接按本机 codex 会话文件存在判定,不再绑 worktree

This commit is contained in:
2026-08-19 19:24:57 +08:00
parent bf3f7f9e67
commit 6251ba0d2a
12 changed files with 190 additions and 21 deletions
+28 -11
View File
@@ -238,8 +238,7 @@ export async function handleResumeReviewSession(panel: KanbanWebviewPanel, sessi
try {
// Server-side prerequisite gate — consistent with handleResumeSession /
// handleImplement. In practice review sessions imply the issue has
// moved past todo (a worktree must exist), but enforcing here keeps
// the contract uniform.
// moved past todo, but enforcing here keeps the contract uniform.
const lockCheck = await panel.resolveLockedReason(issueNumber)
if (lockCheck.locked) {
logger.add({
@@ -257,15 +256,31 @@ export async function handleResumeReviewSession(panel: KanbanWebviewPanel, sessi
existing.show(false)
return
}
// codex resume 只依赖 ~/.codex/sessions 下的 rollout 文件,与 worktree
// 无关:worktree 在则用它当 cwd,否则退回工作区根目录(与
// handleResumeSession 同款回退)。
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath
if (!relCwd || !workspaceRoot) {
void window.showErrorMessage(`审查会话无法恢复 #${issueNumber}worktree 路径未记录`)
if (!workspaceRoot) {
void window.showErrorMessage(`审查会话无法恢复 #${issueNumber}未打开工作区`)
return
}
const worktreeAbs = resolveWorktreePath(relCwd, workspaceRoot)
if (!fs.existsSync(worktreeAbs)) {
void window.showErrorMessage(`审查会话无法恢复 #${issueNumber}worktree 不存在 ${worktreeAbs}`)
return
let effectiveCwd = workspaceRoot
let cwdFallback = true
if (relCwd) {
const worktreeAbs = resolveWorktreePath(relCwd, workspaceRoot)
if (fs.existsSync(worktreeAbs)) {
effectiveCwd = worktreeAbs
cwdFallback = false
}
}
if (cwdFallback) {
panel.postMessage({
type: 'toast/show',
id: makeNonce(),
level: 'info',
message: `工单 #${issueNumber} 的 worktree 不可用,审查会话将在工作区根目录恢复`,
dismissOnTimer: 5000,
})
}
// Scan live terminals before creating a new one — survives panel
// reload / webview rebuild where `this.reviewTerminals` got wiped but
@@ -284,7 +299,7 @@ export async function handleResumeReviewSession(panel: KanbanWebviewPanel, sessi
const { themeColor, iconUri } = await panel.resolveIssueIcon(issueNumber)
const terminal = window.createTerminal({
name: reviewTerminalName,
cwd: worktreeAbs,
cwd: effectiveCwd,
location: panel.resolveTerminalLocation(false),
iconPath: iconUri,
color: themeColor,
@@ -302,7 +317,7 @@ export async function handleResumeReviewSession(panel: KanbanWebviewPanel, sessi
logger.add({
level: 'info',
source: 'terminal',
message: `已创建审查会话终端 #${issueNumber} cwd=${worktreeAbs}`,
message: `已创建审查会话终端 #${issueNumber} cwd=${effectiveCwd}`,
})
}
finally {
@@ -590,10 +605,12 @@ async function triggerAutoReviewTabUnlocked(panel: KanbanWebviewPanel, opts: {
if (!token)
return
await panel.mergeIssueState(opts.issueNumber, { reviewSessionId: threadId })
// reviewSessionFileExists 是计算字段不持久化;rollout 文件刚在本机
// 落盘,patch 里直接置 true 让 resume 链接立即可点。
panel.postMessage({
type: 'issue/patch',
issueNumber: opts.issueNumber,
patch: { reviewSessionId: threadId },
patch: { reviewSessionId: threadId, reviewSessionFileExists: true },
})
}
catch (err) {