✨ feat(vscode): 头脑风暴 profile 独立 + codex 命令统一组装收尾

- 头脑风暴/实施/测试会话 profile 彻底独立,互不回退,各自空值回落默认
- 新建工单弹窗的 profile 选择改为头脑风暴专用 brainstormProfilePath
- 详情面板新增「头脑风暴配置文件」下拉
- 删除从未接线的死代码 reviewFlow.ts(runReview 全仓库无调用方)
- codexCommand 精简为仅 resume/interactive 两种终端命令形态
- 版本号 0.2.55 → 0.2.60
This commit is contained in:
cruldra committed 2026-07-13 07:50:39 +08:00
1 parent 5188c23765
commit b585016cd7
22 files changed
+258 -366

No files matched your search

+98 -12
View File
@@ -1007,7 +1007,7 @@ export async function handleIssueCreate(
panel: KanbanWebviewPanel,
userRequest: string,
images?: Array<{ mediaType: string, base64: string }>,
profilePath?: string,
brainstormProfilePath?: string,
): Promise<void> {
const trimmed = userRequest.trim()
if (!trimmed) {
@@ -1141,13 +1141,13 @@ export async function handleIssueCreate(
}
const effectiveProfilePath
= profilePath && profilePath.trim() !== '' ? profilePath : DEFAULT_PROFILE_PATH
= brainstormProfilePath && brainstormProfilePath.trim() !== '' ? brainstormProfilePath : DEFAULT_PROFILE_PATH
if (effectiveProfilePath.includes('\'')) {
panel.postMessage({
type: 'toast/show',
id: makeNonce(),
level: 'error',
message: `创建失败:profilePath 含单引号,拒绝执行 (${effectiveProfilePath})`,
message: `创建失败:brainstormProfilePath 含单引号,拒绝执行 (${effectiveProfilePath})`,
dismissOnTimer: 8000,
})
try {
@@ -1185,8 +1185,12 @@ export async function handleIssueCreate(
message: `已创建终端 "${terminal.name}"`,
})
// 新建工单会话是头脑风暴;只把用户选中的 brainstorm profile 写入 pending,
// 空串不落盘(webhook 侧也会跳过空值),实施/测试 profile 各自独立配置。
const storedBrainstormProfile
= brainstormProfilePath && brainstormProfilePath.trim() !== '' ? brainstormProfilePath.trim() : undefined
panel.pendingIssueCreations.set(nonce, {
profilePath: effectiveProfilePath,
brainstormProfilePath: storedBrainstormProfile,
color,
workspaceRoot,
inboxDir,
@@ -1572,10 +1576,10 @@ export async function handleUpdateAutoReview(panel: KanbanWebviewPanel, issueNum
/**
* Persist a per-issue `profilePath` override into the issue's state JSON
* comment. The implement / implement-resume / conflict-resolution cc sessions
* launch with this profile (see resolveImplementProfilePath); empty falls back
* to DEFAULT_PROFILE_PATH. Mirrors handleUpdateAutoReview: optimistic update on
* the webview, rolled back via `issue/patch` if the persist fails.
* comment. Implement / implement-resume sessions use this profile
* (see resolveImplementProfilePath); empty = DEFAULT_PROFILE_PATH.
* Mirrors handleUpdateAutoReview: optimistic update on the webview, rolled
* back via `issue/patch` if the persist fails.
*/
export async function handleUpdateProfilePath(panel: KanbanWebviewPanel, issueNumber: number, profilePath: string): Promise<void> {
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath
@@ -1661,12 +1665,94 @@ export async function handleUpdateProfilePath(panel: KanbanWebviewPanel, issueNu
}
}
/**
* Persist a per-issue `brainstormProfilePath` override into the issue's state
* JSON. Brainstorm start/resume use this profile (see resolveBrainstormProfilePath);
* empty = DEFAULT_PROFILE_PATH. 与实施/测试 profile 互不回退。
*/
export async function handleUpdateBrainstormProfilePath(panel: KanbanWebviewPanel, issueNumber: number, brainstormProfilePath: string): Promise<void> {
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath
if (!workspaceRoot) {
panel.postMessage({
type: 'toast/show',
id: makeNonce(),
level: 'error',
message: '请先打开一个工作区文件夹',
dismissOnTimer: 5000,
})
return
}
const remote = await detectRepo(workspaceRoot)
if (!remote) {
panel.postMessage({
type: 'toast/show',
id: makeNonce(),
level: 'error',
message: '当前工作区没有 Gitea 远程仓库',
dismissOnTimer: 5000,
})
return
}
const token = await getToken(panel.context, remote.host)
if (!token) {
panel.postMessage({
type: 'toast/show',
id: makeNonce(),
level: 'error',
message: '请先完成 Gitea 配置',
dismissOnTimer: 5000,
})
return
}
let previousValue: string | undefined
try {
const existingState = await panel.readIssueState(issueNumber)
previousValue = typeof existingState.brainstormProfilePath === 'string'
? existingState.brainstormProfilePath
: undefined
}
catch {
previousValue = undefined
}
try {
await panel.mergeIssueState(issueNumber, { brainstormProfilePath })
logger.add({
level: 'info',
source: 'panel',
message: `工单 #${issueNumber} brainstormProfilePath=${brainstormProfilePath} 已持久化`,
})
}
catch (err) {
const message = err instanceof Error ? err.message : String(err)
logger.add({
level: 'error',
source: 'panel',
message: `持久化 brainstormProfilePath 失败 (issue #${issueNumber})`,
details: message,
})
panel.postMessage({
type: 'toast/show',
id: makeNonce(),
level: 'error',
message: `保存工单 #${issueNumber} 头脑风暴配置文件失败: ${message}`,
dismissOnTimer: 6000,
})
panel.postMessage({
type: 'issue/patch',
issueNumber,
patch: { brainstormProfilePath: previousValue },
})
}
}
/**
* Persist a per-issue `testProfilePath` override into the issue's state JSON
* comment. The manually-started test cc session launches with this profile
* (see resolveTestProfilePath); empty falls back to the implement `profilePath`,
* then DEFAULT_PROFILE_PATH. Mirrors handleUpdateProfilePath: optimistic update
* on the webview, rolled back via `issue/patch` if the persist fails.
* comment. Test start/resume use this profile (see resolveTestProfilePath);
* empty = DEFAULT_PROFILE_PATH,不回退实施 profile。
*/
export async function handleUpdateTestProfilePath(panel: KanbanWebviewPanel, issueNumber: number, testProfilePath: string): Promise<void> {
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath