♻️ refactor(vscode): claude 会话命令收口到 buildCcCommand 并移除已卸载的 serena --system-prompt
9 处手拼的 claude 启动命令(managedSessions/sessions/issues)统一改用新增的
cc/ccCommand.ts:buildCcCommand({ profilePath, effort?, resumeSessionId?, prompt? }),
去掉各处重复的 --system-prompt="$(serena prompts ...)"(serena 已卸载)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Single source of truth for the `claude` (cc) terminal launch command.
|
||||||
|
*
|
||||||
|
* Every session entry point (brainstorm / implement / test / review / resume /
|
||||||
|
* managed session) shells out `claude` with the same flags; building the
|
||||||
|
* string in one place keeps those call sites from drifting apart.
|
||||||
|
*
|
||||||
|
* We deliberately pass no `--system-prompt`; cc runs with its own default
|
||||||
|
* system prompt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface CcCommandOpts {
|
||||||
|
/** Path passed to `--settings` (caller guarantees it contains no single quote). */
|
||||||
|
profilePath: string
|
||||||
|
/** e.g. 'high' → `--effort high`; omitted means no `--effort`. */
|
||||||
|
effort?: string
|
||||||
|
/** When set, append `--resume <id>`. Mutually exclusive with prompt; resume wins. */
|
||||||
|
resumeSessionId?: string
|
||||||
|
/** When set (and no resume), append the prompt as a positional `'<prompt>'` arg. */
|
||||||
|
prompt?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildCcCommand(opts: CcCommandOpts): string {
|
||||||
|
const parts = ['claude']
|
||||||
|
if (opts.effort)
|
||||||
|
parts.push(`--effort ${opts.effort}`)
|
||||||
|
parts.push('--dangerously-skip-permissions', `--settings '${opts.profilePath}'`)
|
||||||
|
// resume and prompt are mutually exclusive; a resumed session restores its
|
||||||
|
// own conversation, so a fresh prompt would be meaningless.
|
||||||
|
if (opts.resumeSessionId)
|
||||||
|
parts.push(`--resume ${opts.resumeSessionId}`)
|
||||||
|
else if (opts.prompt)
|
||||||
|
parts.push(`'${opts.prompt}'`)
|
||||||
|
return parts.join(' ')
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import * as path from 'node:path'
|
|||||||
import { resolveWorktreePath } from '../../git/worktree'
|
import { resolveWorktreePath } from '../../git/worktree'
|
||||||
import { commands, env, ThemeColor, Uri, window, workspace } from 'vscode'
|
import { commands, env, ThemeColor, Uri, window, workspace } from 'vscode'
|
||||||
import { getToken } from '../../auth/secrets'
|
import { getToken } from '../../auth/secrets'
|
||||||
|
import { buildCcCommand } from '../../cc/ccCommand'
|
||||||
import { getBrainstormPrompt } from '../../cc/prompts'
|
import { getBrainstormPrompt } from '../../cc/prompts'
|
||||||
import { projectsDirFor, watchForNewSession } from '../../cc/sessionWatcher'
|
import { projectsDirFor, watchForNewSession } from '../../cc/sessionWatcher'
|
||||||
import { spawnClaude } from '../../cc/spawnClaude'
|
import { spawnClaude } from '../../cc/spawnClaude'
|
||||||
@@ -1283,7 +1284,7 @@ export async function handleIssueCreate(
|
|||||||
createdAt: Date.now(),
|
createdAt: Date.now(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const cmd = `claude --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)" '${prompt}'`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, prompt })
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
logger.add({
|
logger.add({
|
||||||
level: 'info',
|
level: 'info',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { KanbanWebviewPanel } from '../KanbanPanel'
|
import type { KanbanWebviewPanel } from '../KanbanPanel'
|
||||||
import { promises as fsp } from 'node:fs'
|
import { promises as fsp } from 'node:fs'
|
||||||
import { window, workspace } from 'vscode'
|
import { window, workspace } from 'vscode'
|
||||||
|
import { buildCcCommand } from '../../cc/ccCommand'
|
||||||
import { pollForNewSession, projectsDirFor } from '../../cc/sessionWatcher'
|
import { pollForNewSession, projectsDirFor } from '../../cc/sessionWatcher'
|
||||||
import { logger } from '../../logging/logger'
|
import { logger } from '../../logging/logger'
|
||||||
import { readManagedSessions, writeManagedSessions } from '../../sessions/managedStore'
|
import { readManagedSessions, writeManagedSessions } from '../../sessions/managedStore'
|
||||||
@@ -53,9 +54,8 @@ export async function handleManagedSessionsGet(panel: KanbanWebviewPanel): Promi
|
|||||||
/**
|
/**
|
||||||
* 从会话管理 tab 创建一个新的 cc 会话:
|
* 从会话管理 tab 创建一个新的 cc 会话:
|
||||||
* - cwd 用项目根(workspaceRoot,非 worktree)。
|
* - cwd 用项目根(workspaceRoot,非 worktree)。
|
||||||
* - 启动命令照搬头脑风暴风格(claude --dangerously-skip-permissions --settings
|
* - 启动命令统一由 buildCcCommand 构建(claude --dangerously-skip-permissions
|
||||||
* '<profilePath>' --system-prompt="$(serena prompts ...)"),prompt 非空时
|
* --settings '<profilePath>'),prompt 非空时作为位置参数传入。
|
||||||
* 再追加 ' <prompt>'。
|
|
||||||
* - 用 pollForNewSession 捕获新 sessionId(共享 projects 目录用轮询更可靠),
|
* - 用 pollForNewSession 捕获新 sessionId(共享 projects 目录用轮询更可靠),
|
||||||
* 落进 .spx/session-names.json 后推全量列表。
|
* 落进 .spx/session-names.json 后推全量列表。
|
||||||
*/
|
*/
|
||||||
@@ -121,9 +121,7 @@ export async function handleManagedSessionsCreate(panel: KanbanWebviewPanel, pro
|
|||||||
message: `已创建终端 "${terminal.name}"`,
|
message: `已创建终端 "${terminal.name}"`,
|
||||||
})
|
})
|
||||||
|
|
||||||
let cmd = `claude --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)"`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, prompt: effectivePrompt || undefined })
|
||||||
if (effectivePrompt)
|
|
||||||
cmd += ` '${effectivePrompt}'`
|
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
logger.add({
|
logger.add({
|
||||||
level: 'info',
|
level: 'info',
|
||||||
@@ -243,7 +241,7 @@ export async function handleManagedSessionsResume(panel: KanbanWebviewPanel, ses
|
|||||||
message: `已创建终端 "${terminal.name}" (resume ${sessionId})`,
|
message: `已创建终端 "${terminal.name}" (resume ${sessionId})`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const cmd = `claude --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)" --resume ${sessionId}`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, resumeSessionId: sessionId })
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
|
|
||||||
// 登记终端并推 show,让列表的 tabOpen 立即为 true。
|
// 登记终端并推 show,让列表的 tabOpen 立即为 true。
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import * as os from 'node:os'
|
|||||||
import * as path from 'node:path'
|
import * as path from 'node:path'
|
||||||
import { window, workspace } from 'vscode'
|
import { window, workspace } from 'vscode'
|
||||||
import { getToken } from '../../auth/secrets'
|
import { getToken } from '../../auth/secrets'
|
||||||
|
import { buildCcCommand } from '../../cc/ccCommand'
|
||||||
import { watchForNewCodexSession } from '../../cc/codexSessionWatcher'
|
import { watchForNewCodexSession } from '../../cc/codexSessionWatcher'
|
||||||
import { getBrainstormContinuePrompt, getImplementPlanPrompt } from '../../cc/prompts'
|
import { getBrainstormContinuePrompt, getImplementPlanPrompt } from '../../cc/prompts'
|
||||||
import { projectsDirFor, watchForNewSession } from '../../cc/sessionWatcher'
|
import { projectsDirFor, watchForNewSession } from '../../cc/sessionWatcher'
|
||||||
@@ -205,8 +206,7 @@ export async function handleResumeSession(panel: KanbanWebviewPanel, sessionId:
|
|||||||
dismissOnTimer: 5000,
|
dismissOnTimer: 5000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const effortArg = sessionKind === 'implement' ? ' --effort high' : ''
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, effort: sessionKind === 'implement' ? 'high' : undefined, resumeSessionId: sessionId })
|
||||||
const cmd = `claude${effortArg} --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)" --resume ${sessionId}`
|
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -870,7 +870,7 @@ export async function handleImplement(
|
|||||||
source: 'terminal',
|
source: 'terminal',
|
||||||
message: `已创建终端 "${terminal.name}"`,
|
message: `已创建终端 "${terminal.name}"`,
|
||||||
})
|
})
|
||||||
const cmd = `claude --effort high --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)" '${prompt}'`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, effort: 'high', prompt })
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
logger.add({
|
logger.add({
|
||||||
level: 'info',
|
level: 'info',
|
||||||
@@ -1020,7 +1020,7 @@ export async function handleStartBrainstormSession(panel: KanbanWebviewPanel, is
|
|||||||
message: `已创建终端 "${terminal.name}"`,
|
message: `已创建终端 "${terminal.name}"`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const cmd = `claude --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)" '${prompt}'`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, prompt })
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
logger.add({
|
logger.add({
|
||||||
level: 'info',
|
level: 'info',
|
||||||
@@ -1220,7 +1220,7 @@ export async function handleStartTestSession(panel: KanbanWebviewPanel, issueNum
|
|||||||
message: `已创建终端 "${terminal.name}"`,
|
message: `已创建终端 "${terminal.name}"`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const cmd = `claude --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)" '${prompt}'`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, prompt })
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
logger.add({
|
logger.add({
|
||||||
level: 'info',
|
level: 'info',
|
||||||
@@ -1366,7 +1366,7 @@ export async function handleResumeTestSession(panel: KanbanWebviewPanel, session
|
|||||||
message: `已创建测试会话终端 #${issueNumber} cwd=${effectiveCwd}`,
|
message: `已创建测试会话终端 #${issueNumber} cwd=${effectiveCwd}`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const cmd = `claude --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt=\"$(serena prompts print-cc-system-prompt-override)\" --resume ${sessionId}`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, resumeSessionId: sessionId })
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -1568,7 +1568,7 @@ export async function startConflictResolution(panel: KanbanWebviewPanel, opts: {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const cmd = `claude --effort high --dangerously-skip-permissions --settings '${effectiveProfilePath}' --system-prompt="$(serena prompts print-cc-system-prompt-override)" '${prompt}'`
|
const cmd = buildCcCommand({ profilePath: effectiveProfilePath, effort: 'high', prompt })
|
||||||
terminal.sendText(cmd)
|
terminal.sendText(cmd)
|
||||||
|
|
||||||
logger.add({
|
logger.add({
|
||||||
|
|||||||
Reference in New Issue
Block a user