✨ feat(vscode): 设置面板可配置 Claude profiles 目录并修正探测顺序
This commit is contained in:
@@ -36,11 +36,8 @@ import * as worktree from './handlers/worktree'
|
||||
import * as youtrackIssues from './handlers/youtrackIssues'
|
||||
import { PALETTE, resolveIssueColor, themeColorIdToIconUri } from './issueColor'
|
||||
|
||||
export const DEFAULT_PROFILE_PATH = '/home/cruldra/Sources/cruldra-profile/claude-config/profiles/offical.json'
|
||||
|
||||
/** PR 变更摘要等后台内容生成任务用的 profile:DeepSeek(自带 token + base_url,
|
||||
* headless 稳定,不依赖订阅 OAuth,避免 403 Request not allowed)。 */
|
||||
export const PR_DIFF_SUMMARY_PROFILE_PATH = '/home/cruldra/Sources/cruldra-profile/claude-config/profiles/deepseek.json'
|
||||
/** Resolved at runtime via getProfilesDir() — do not hardcode user paths. */
|
||||
export { getDefaultProfilePath, getPrDiffSummaryProfilePath } from '../cc/profiles'
|
||||
|
||||
export class KanbanWebviewPanel {
|
||||
static readonly viewType = 'superpowers.kanbanPanel'
|
||||
@@ -861,6 +858,7 @@ export class KanbanWebviewPanel {
|
||||
conflictResolutionProfilePath: s.conflictResolutionProfilePath,
|
||||
codexModel: s.codexModel,
|
||||
codexReasoningEffort: s.codexReasoningEffort,
|
||||
profilesDirectory: s.profilesDirectory,
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -926,6 +924,7 @@ export class KanbanWebviewPanel {
|
||||
conflictResolutionProfilePath: s.conflictResolutionProfilePath,
|
||||
codexModel: s.codexModel,
|
||||
codexReasoningEffort: s.codexReasoningEffort,
|
||||
profilesDirectory: s.profilesDirectory,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { buildCcCommand } from '../../cc/ccCommand'
|
||||
import { pollForNewSession, projectsDirFor } from '../../cc/sessionWatcher'
|
||||
import { logger } from '../../logging/logger'
|
||||
import { readManagedSessions, writeManagedSessions } from '../../sessions/managedStore'
|
||||
import { DEFAULT_PROFILE_PATH } from '../KanbanPanel'
|
||||
import { resolveProfilePath } from '../../cc/profiles'
|
||||
|
||||
/** 默认会话名:有 prompt 取前 20 字符,否则用短 id(前 8 位)。 */
|
||||
function defaultSessionName(sessionId: string, prompt?: string): string {
|
||||
@@ -66,8 +66,9 @@ export async function handleManagedSessionsCreate(panel: KanbanWebviewPanel, pro
|
||||
return
|
||||
}
|
||||
|
||||
const effectiveProfilePath
|
||||
= profilePath && profilePath.trim() !== '' ? profilePath : DEFAULT_PROFILE_PATH
|
||||
const effectiveProfilePath = resolveProfilePath(
|
||||
profilePath && profilePath.trim() !== '' ? profilePath : undefined,
|
||||
)
|
||||
// 单引号会破坏下面的 shell 单引号包裹,防御性拒绝(与现有 handler 一致)。
|
||||
if (effectiveProfilePath.includes('\'')) {
|
||||
void window.showErrorMessage(
|
||||
@@ -219,8 +220,9 @@ export async function handleManagedSessionsResume(panel: KanbanWebviewPanel, ses
|
||||
const data = await readManagedSessions(workspaceRoot)
|
||||
const target = data.sessions.find(s => s.id === sessionId)
|
||||
|
||||
const effectiveProfilePath
|
||||
= target?.profilePath && target.profilePath.trim() !== '' ? target.profilePath : DEFAULT_PROFILE_PATH
|
||||
const effectiveProfilePath = resolveProfilePath(
|
||||
target?.profilePath && target.profilePath.trim() !== '' ? target.profilePath : undefined,
|
||||
)
|
||||
if (effectiveProfilePath.includes('\'')) {
|
||||
void window.showErrorMessage(
|
||||
`resume 失败:profilePath 含单引号,拒绝执行 (${effectiveProfilePath})`,
|
||||
|
||||
@@ -18,7 +18,8 @@ import { createWorktree, resolveWorktreePath } from '../../git/worktree'
|
||||
import { logger } from '../../logging/logger'
|
||||
import { getSettings } from '../../settings/store'
|
||||
import { webhookCoordinator } from '../../webhook/coordinator'
|
||||
import { DEFAULT_PROFILE_PATH, makeNonce } from '../KanbanPanel'
|
||||
import { resolveProfilePath } from '../../cc/profiles'
|
||||
import { makeNonce } from '../KanbanPanel'
|
||||
|
||||
export async function handleResumeSession(panel: KanbanWebviewPanel, sessionId: string, profilePath?: string, relCwd?: string, issueNumber?: number): Promise<void> {
|
||||
// kind 跟着 sessionRole 提前判定(原来散落在方法中部,提到入口是为了构造
|
||||
@@ -1562,9 +1563,11 @@ export async function startConflictResolution(panel: KanbanWebviewPanel, opts: {
|
||||
return
|
||||
}
|
||||
terminal.show(false)
|
||||
// 冲突解决只用全局设置 conflictResolutionProfilePath;空串 = DEFAULT_PROFILE_PATH。
|
||||
const effectiveProfilePath
|
||||
= settings.conflictResolutionProfilePath.trim() || DEFAULT_PROFILE_PATH
|
||||
// 冲突解决只用全局设置 conflictResolutionProfilePath;空串 = 默认。
|
||||
// 工单/设置里可能持久化了跨机绝对路径,统一走 resolveProfilePath remapping。
|
||||
const effectiveProfilePath = resolveProfilePath(
|
||||
settings.conflictResolutionProfilePath.trim() || undefined,
|
||||
)
|
||||
if (effectiveProfilePath.includes('\'')) {
|
||||
logger.add({
|
||||
level: 'error',
|
||||
@@ -1603,17 +1606,14 @@ export async function startConflictResolution(panel: KanbanWebviewPanel, opts: {
|
||||
* (handleImplement / handleResumeSession when sessionKind === 'implement')
|
||||
* should launch with. Priority:
|
||||
* 1. 工单级 `profilePath`(详情面板「实施配置文件」)
|
||||
* 2. DEFAULT_PROFILE_PATH
|
||||
* 2. getDefaultProfilePath()
|
||||
*
|
||||
* 冲突解决用全局 `settings.conflictResolutionProfilePath`。
|
||||
* 头脑风暴用 resolveBrainstormProfilePath;测试用 resolveTestProfilePath。
|
||||
* 三者互不回退。
|
||||
*/
|
||||
export function resolveImplementProfilePath(_panel: KanbanWebviewPanel, issueLevelProfilePath: string | undefined): string {
|
||||
const issueLevel = issueLevelProfilePath?.trim()
|
||||
if (issueLevel)
|
||||
return issueLevel
|
||||
return DEFAULT_PROFILE_PATH
|
||||
return resolveProfilePath(issueLevelProfilePath?.trim() || undefined)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1621,7 +1621,7 @@ export function resolveImplementProfilePath(_panel: KanbanWebviewPanel, issueLev
|
||||
* 不回退实施 profile。
|
||||
*/
|
||||
export function resolveBrainstormProfilePath(_panel: KanbanWebviewPanel, brainstormProfilePath: string | undefined): string {
|
||||
return brainstormProfilePath?.trim() || DEFAULT_PROFILE_PATH
|
||||
return resolveProfilePath(brainstormProfilePath?.trim() || undefined)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1629,7 +1629,7 @@ export function resolveBrainstormProfilePath(_panel: KanbanWebviewPanel, brainst
|
||||
* 不回退实施 profile。
|
||||
*/
|
||||
export function resolveTestProfilePath(_panel: KanbanWebviewPanel, testProfilePath: string | undefined): string {
|
||||
return testProfilePath?.trim() || DEFAULT_PROFILE_PATH
|
||||
return resolveProfilePath(testProfilePath?.trim() || undefined)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as os from 'node:os'
|
||||
import * as path from 'node:path'
|
||||
import { commands, env, Uri, workspace } from 'vscode'
|
||||
import { getToken, getYouTrackToken, setToken, setYouTrackToken } from '../../auth/secrets'
|
||||
import { listClaudeProfiles } from '../../cc/profiles'
|
||||
import { listClaudeProfiles, setProfilesDirOverride } from '../../cc/profiles'
|
||||
import { detectRepo } from '../../git/remote'
|
||||
import { logger } from '../../logging/logger'
|
||||
import { readProfiles, writeProfiles } from '../../profiles/store'
|
||||
@@ -35,6 +35,7 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
conflictResolutionProfilePath: string
|
||||
codexModel: string
|
||||
codexReasoningEffort: string
|
||||
profilesDirectory: string
|
||||
youtrackBaseUrl: string
|
||||
youtrackProjectShortName: string
|
||||
youtrackCloseCommand: string
|
||||
@@ -66,6 +67,8 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
// codex 模型 / 思考级别:空串有意义(= 用 codex 默认),只 trim。
|
||||
const trimmedCodexModel = payload.codexModel.trim()
|
||||
const trimmedCodexReasoningEffort = payload.codexReasoningEffort.trim()
|
||||
// profiles 目录:空串有意义(= 自动探测),只 trim。
|
||||
const trimmedProfilesDirectory = payload.profilesDirectory.trim()
|
||||
const prev = getSettings(panel.context)
|
||||
// Capture the previous token *for this host* before overwriting it, so
|
||||
// we can decide below whether the kanban needs a re-fetch. (Only host
|
||||
@@ -98,6 +101,7 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
conflictResolutionProfilePath: trimmedConflictProfile,
|
||||
codexModel: trimmedCodexModel,
|
||||
codexReasoningEffort: trimmedCodexReasoningEffort,
|
||||
profilesDirectory: trimmedProfilesDirectory,
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -122,10 +126,14 @@ export async function handleSettingsSave(panel: KanbanWebviewPanel, payload: {
|
||||
conflictResolutionProfilePath: trimmedConflictProfile,
|
||||
codexModel: trimmedCodexModel,
|
||||
codexReasoningEffort: trimmedCodexReasoningEffort,
|
||||
profilesDirectory: trimmedProfilesDirectory,
|
||||
youtrackBaseUrl: trimmedYtBase,
|
||||
youtrackProjectShortName: trimmedYtProject,
|
||||
youtrackCloseCommand: trimmedYtClose,
|
||||
})
|
||||
// 保存后立刻让 listClaudeProfiles / getDefaultProfilePath 吃到新目录。
|
||||
setProfilesDirOverride(trimmedProfilesDirectory || undefined)
|
||||
void handleProfilesList(panel)
|
||||
if (!keepExisting)
|
||||
await setToken(panel.context, trimmedHost, trimmedToken)
|
||||
// YouTrack token: stored under the base URL's host. Empty input keeps the
|
||||
@@ -179,6 +187,8 @@ export async function handleEditSettingsRequest(panel: KanbanWebviewPanel): Prom
|
||||
host = remote.host
|
||||
}
|
||||
const s = getSettings(panel.context)
|
||||
// 打开设置时同步 override,避免未 activate 路径或旧值漂移。
|
||||
setProfilesDirOverride(s.profilesDirectory || undefined)
|
||||
const tok = host ? await getToken(panel.context, host) : undefined
|
||||
const tokenSaved = !!tok && tok.length > 0
|
||||
const ytTok = s.youtrackBaseUrl.trim()
|
||||
@@ -207,6 +217,7 @@ export async function handleEditSettingsRequest(panel: KanbanWebviewPanel): Prom
|
||||
conflictResolutionProfilePath: s.conflictResolutionProfilePath,
|
||||
codexModel: s.codexModel,
|
||||
codexReasoningEffort: s.codexReasoningEffort,
|
||||
profilesDirectory: s.profilesDirectory,
|
||||
youtrackBaseUrl: s.youtrackBaseUrl,
|
||||
youtrackProjectShortName: s.youtrackProjectShortName,
|
||||
youtrackCloseCommand: s.youtrackCloseCommand,
|
||||
|
||||
@@ -69,6 +69,7 @@ export type ExtensionToWebview
|
||||
conflictResolutionProfilePath: string
|
||||
codexModel: string
|
||||
codexReasoningEffort: string
|
||||
profilesDirectory: string
|
||||
youtrackBaseUrl?: string
|
||||
youtrackProjectShortName?: string
|
||||
youtrackCloseCommand?: string
|
||||
@@ -133,6 +134,7 @@ export type WebviewToExtension
|
||||
conflictResolutionProfilePath: string
|
||||
codexModel: string
|
||||
codexReasoningEffort: string
|
||||
profilesDirectory: string
|
||||
youtrackBaseUrl: string
|
||||
youtrackProjectShortName: string
|
||||
youtrackCloseCommand: string
|
||||
|
||||
Reference in New Issue
Block a user