✨ feat(vscode): 设置面板可配头脑风暴/实施/测试会话的默认 profile

三类会话的 profile 此前只有工单级字段,留空就硬编码落到 official,
想整体换模型只能一个工单一个工单改。

设置面板新增三个下拉,与冲突解决/提交/改动说明的 profile 选择同区。
解析链路变成:工单级字段 > 对应的全局默认设置 > getDefaultProfilePath(),
三类之间仍互不回退。新建工单的头脑风暴会话也走同一条链路。

Claude-Session: https://claude.ai/code/session_01REdhpbaNyqWASF2HWsnTFv
This commit is contained in:
cruldra committed 2026-09-13 08:59:56 +08:00
1 parent 518d471b7a
commit 958c59e090
11 files changed
+196 -18

No files matched your search

+6
View File
@@ -970,6 +970,9 @@ export class KanbanWebviewPanel {
implTabPreCreateScript: s.implTabPreCreateScript,
implTabPostCloseScript: s.implTabPostCloseScript,
splitNewTerminals: s.splitNewTerminals,
defaultBrainstormProfilePath: s.defaultBrainstormProfilePath,
defaultImplementProfilePath: s.defaultImplementProfilePath,
defaultTestProfilePath: s.defaultTestProfilePath,
conflictResolutionProfilePath: s.conflictResolutionProfilePath,
commitProfilePath: await getEffectiveCommitProfilePath(this.context),
prDiffSummaryProfilePath: await getEffectivePrDiffSummaryProfilePath(this.context),
@@ -1055,6 +1058,9 @@ export class KanbanWebviewPanel {
implTabPreCreateScript: s.implTabPreCreateScript,
implTabPostCloseScript: s.implTabPostCloseScript,
splitNewTerminals: s.splitNewTerminals,
defaultBrainstormProfilePath: s.defaultBrainstormProfilePath,
defaultImplementProfilePath: s.defaultImplementProfilePath,
defaultTestProfilePath: s.defaultTestProfilePath,
conflictResolutionProfilePath: s.conflictResolutionProfilePath,
commitProfilePath: await getEffectiveCommitProfilePath(this.context),
prDiffSummaryProfilePath: await getEffectivePrDiffSummaryProfilePath(this.context),
+6 -6
View File
@@ -10,7 +10,7 @@ import { commands, env, ThemeColor, Uri, window, workspace } from 'vscode'
import { getToken } from '../../auth/secrets'
import { buildCcCommand } from '../../cc/ccCommand'
import { resolveCommitProfileForRun } from '../../cc/commitProfile'
import { getDefaultProfilePath, resolveProfilePath } from '../../cc/profiles'
import { resolveProfilePath } from '../../cc/profiles'
import { getBrainstormPrompt } from '../../cc/prompts'
import { claudeProjectsRoot, installClaudeSession } from '../../cc/sessionBundle'
import { projectsDirFor, watchForNewSession } from '../../cc/sessionWatcher'
@@ -1429,8 +1429,8 @@ export async function handleIssueCreate(
return
}
const effectiveProfilePath
= brainstormProfilePath && brainstormProfilePath.trim() !== '' ? brainstormProfilePath : getDefaultProfilePath()
// 新建工单弹窗里选的 profile > 设置里的「头脑风暴默认配置文件」> DEFAULT。
const effectiveProfilePath = sessions.resolveBrainstormProfilePath(panel, brainstormProfilePath)
if (effectiveProfilePath.includes('\'')) {
panel.postMessage({
type: 'toast/show',
@@ -1888,7 +1888,7 @@ export async function handleUpdateAutoReview(panel: KanbanWebviewPanel, issueNum
/**
* Persist a per-issue `profilePath` override into the issue's state JSON
* comment. Implement / implement-resume sessions use this profile
* (see resolveImplementProfilePath); empty = getDefaultProfilePath().
* (see resolveImplementProfilePath); empty = 设置里的「实施默认配置文件」,再空 = getDefaultProfilePath()。
* Mirrors handleUpdateAutoReview: optimistic update on the webview, rolled
* back via `issue/patch` if the persist fails.
*/
@@ -1979,7 +1979,7 @@ 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 = getDefaultProfilePath(). 与实施/测试 profile 互不回退。
* empty = 设置里的「头脑风暴默认配置文件」,再空 = getDefaultProfilePath()。与实施/测试 profile 互不回退。
*/
export async function handleUpdateBrainstormProfilePath(panel: KanbanWebviewPanel, issueNumber: number, brainstormProfilePath: string): Promise<void> {
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath
@@ -2063,7 +2063,7 @@ export async function handleUpdateBrainstormProfilePath(panel: KanbanWebviewPane
/**
* Persist a per-issue `testProfilePath` override into the issue's state JSON
* comment. Test start/resume use this profile (see resolveTestProfilePath);
* empty = getDefaultProfilePath(),不回退实施 profile。
* empty = 设置里的「测试默认配置文件」,再空 = getDefaultProfilePath(),不回退实施 profile。
*/
export async function handleUpdateTestProfilePath(panel: KanbanWebviewPanel, issueNumber: number, testProfilePath: string): Promise<void> {
const workspaceRoot = workspace.workspaceFolders?.[0]?.uri.fsPath
+24 -11
View File
@@ -1599,30 +1599,43 @@ export async function startConflictResolution(panel: KanbanWebviewPanel, opts: {
* (handleImplement / handleResumeSession when sessionKind === 'implement')
* should launch with. Priority:
* 1. 工单级 `profilePath`(详情面板「实施配置文件」)
* 2. getDefaultProfilePath()
* 2. 设置里的「实施默认配置文件」
* 3. getDefaultProfilePath()
*
* 冲突解决用全局 `settings.conflictResolutionProfilePath`。
* 头脑风暴用 resolveBrainstormProfilePath;测试用 resolveTestProfilePath。
* 三者互不回退。
*/
export function resolveImplementProfilePath(_panel: KanbanWebviewPanel, issueLevelProfilePath: string | undefined): string {
return resolveProfilePath(issueLevelProfilePath?.trim() || undefined)
export function resolveImplementProfilePath(panel: KanbanWebviewPanel, issueLevelProfilePath: string | undefined): string {
return resolveProfilePath(
issueLevelProfilePath?.trim()
|| getSettings(panel.context).defaultImplementProfilePath.trim()
|| undefined,
)
}
/**
* 头脑风暴会话 profile:工单级 `brainstormProfilePath` > DEFAULT。
* 不回退实施 profile。
* 头脑风暴会话 profile:工单级 `brainstormProfilePath` > 设置里的
* 「头脑风暴默认配置文件」> DEFAULT。不回退实施 profile。
*/
export function resolveBrainstormProfilePath(_panel: KanbanWebviewPanel, brainstormProfilePath: string | undefined): string {
return resolveProfilePath(brainstormProfilePath?.trim() || undefined)
export function resolveBrainstormProfilePath(panel: KanbanWebviewPanel, brainstormProfilePath: string | undefined): string {
return resolveProfilePath(
brainstormProfilePath?.trim()
|| getSettings(panel.context).defaultBrainstormProfilePath.trim()
|| undefined,
)
}
/**
* 测试会话 profile:工单级 `testProfilePath` > DEFAULT。
* 不回退实施 profile。
* 测试会话 profile:工单级 `testProfilePath` > 设置里的「测试默认配置文件」
* > DEFAULT。不回退实施 profile。
*/
export function resolveTestProfilePath(_panel: KanbanWebviewPanel, testProfilePath: string | undefined): string {
return resolveProfilePath(testProfilePath?.trim() || undefined)
export function resolveTestProfilePath(panel: KanbanWebviewPanel, testProfilePath: string | undefined): string {
return resolveProfilePath(
testProfilePath?.trim()
|| getSettings(panel.context).defaultTestProfilePath.trim()
|| undefined,
)
}
/**
+16
View File
@@ -39,6 +39,9 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
implTabPreCreateScript: string
implTabPostCloseScript: string
splitNewTerminals: boolean
defaultBrainstormProfilePath: string
defaultImplementProfilePath: string
defaultTestProfilePath: string
conflictResolutionProfilePath: string
commitProfilePath: string
prDiffSummaryProfilePath: string
@@ -74,6 +77,10 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
const trimmedPreRemove = payload.worktreePreRemoveScript.trim()
const trimmedImplPre = payload.implTabPreCreateScript.trim()
const trimmedImplPost = payload.implTabPostCloseScript.trim()
// 三个会话默认 profile:'' 有意义(= 落到 DEFAULT_PROFILE_PATH),只 trim。
const trimmedDefaultBrainstormProfile = payload.defaultBrainstormProfilePath.trim()
const trimmedDefaultImplementProfile = payload.defaultImplementProfilePath.trim()
const trimmedDefaultTestProfile = payload.defaultTestProfilePath.trim()
// conflict-resolution profile: '' is meaningful (= DEFAULT_PROFILE_PATH).
const trimmedConflictProfile = payload.conflictResolutionProfilePath.trim()
// 提交代码 profile:'' 有意义(= 未配置 → 提交严格失败),只 trim。
@@ -118,6 +125,9 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
implTabPreCreateScript: trimmedImplPre,
implTabPostCloseScript: trimmedImplPost,
splitNewTerminals: payload.splitNewTerminals,
defaultBrainstormProfilePath: trimmedDefaultBrainstormProfile,
defaultImplementProfilePath: trimmedDefaultImplementProfile,
defaultTestProfilePath: trimmedDefaultTestProfile,
conflictResolutionProfilePath: trimmedConflictProfile,
commitProfilePath: trimmedCommitProfile,
prDiffSummaryProfilePath: trimmedPrDiffSummaryProfile,
@@ -147,6 +157,9 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
implTabPreCreateScript: trimmedImplPre,
implTabPostCloseScript: trimmedImplPost,
splitNewTerminals: payload.splitNewTerminals,
defaultBrainstormProfilePath: trimmedDefaultBrainstormProfile,
defaultImplementProfilePath: trimmedDefaultImplementProfile,
defaultTestProfilePath: trimmedDefaultTestProfile,
conflictResolutionProfilePath: trimmedConflictProfile,
commitProfilePath: trimmedCommitProfile,
prDiffSummaryProfilePath: trimmedPrDiffSummaryProfile,
@@ -253,6 +266,9 @@ export async function handleEditSettingsRequest(panel: KanbanWebviewPanel): Prom
implTabPreCreateScript: s.implTabPreCreateScript,
implTabPostCloseScript: s.implTabPostCloseScript,
splitNewTerminals: s.splitNewTerminals,
defaultBrainstormProfilePath: s.defaultBrainstormProfilePath,
defaultImplementProfilePath: s.defaultImplementProfilePath,
defaultTestProfilePath: s.defaultTestProfilePath,
conflictResolutionProfilePath: s.conflictResolutionProfilePath,
commitProfilePath,
prDiffSummaryProfilePath,
+6
View File
@@ -86,6 +86,9 @@ export type ExtensionToWebview
implTabPreCreateScript: string
implTabPostCloseScript: string
splitNewTerminals: boolean
defaultBrainstormProfilePath: string
defaultImplementProfilePath: string
defaultTestProfilePath: string
conflictResolutionProfilePath: string
commitProfilePath: string
prDiffSummaryProfilePath: string
@@ -165,6 +168,9 @@ export type WebviewToExtension
implTabPreCreateScript: string
implTabPostCloseScript: string
splitNewTerminals: boolean
defaultBrainstormProfilePath: string
defaultImplementProfilePath: string
defaultTestProfilePath: string
conflictResolutionProfilePath: string
commitProfilePath: string
prDiffSummaryProfilePath: string