From 5bfd7598225a1e1c5aef38a4fde9e0db0f90339b Mon Sep 17 00:00:00 2001 From: cruldra Date: Sun, 13 Sep 2026 09:21:53 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(vscode):=20=E5=A4=B4=E8=84=91?= =?UTF-8?q?=E9=A3=8E=E6=9A=B4=E4=BC=9A=E8=AF=9D=E5=8F=AF=E6=B8=85=E9=99=A4?= =?UTF-8?q?=EF=BC=8C=E6=82=AC=E5=81=9C=E6=8F=90=E7=A4=BA=E6=94=B9=E7=AA=84?= =?UTF-8?q?=E6=94=B9=E7=B4=A7=E5=87=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 工单记着的头脑风暴会话 id 此前没有清除入口,续聊只能 resume 旧会话, 把几个版本前的提示词和它当时报的错一起带回来。会话 id 行新增清除按钮, 确认后把 state JSON 的 sessionId 置空,下次续聊新开会话;会话文件不动, 手上有 id 仍可 claude --resume 找回。 悬停气泡此前贴着视口右边测量尺寸:fixed 元素的可用宽度是「视口宽 - left」, 贴边测会被挤窄、行数变多,按那个高度定位就浮高一截。改成先在左上角量再落位, 字号行高收紧,提示文案压成一行。顺带修掉「重置为待办」的错误说明——它会停 会话、删 worktree 和未合并 PR,不是原样保留。 Claude-Session: https://claude.ai/code/session_01REdhpbaNyqWASF2HWsnTFv --- vscode/package.json | 2 +- vscode/src/panel/KanbanPanel.ts | 4 ++ vscode/src/panel/handlers/issues.ts | 71 +++++++++++++++++++ vscode/src/panel/messages.ts | 1 + vscode/src/panel/readOnlyGuard.ts | 1 + vscode/webview-ui/src/App.tsx | 2 + .../webview-ui/src/components/BottomTabs.tsx | 2 + .../src/components/IssueDetailPanel.tsx | 30 +++++--- .../webview-ui/src/components/ui/tooltip.tsx | 23 +++--- vscode/webview-ui/src/hooks/useIssues.ts | 10 ++- vscode/webview-ui/src/lib/messages.ts | 1 + 11 files changed, 124 insertions(+), 23 deletions(-) diff --git a/vscode/package.json b/vscode/package.json index f0438c4..f78fbc7 100644 --- a/vscode/package.json +++ b/vscode/package.json @@ -2,7 +2,7 @@ "publisher": "clurdra", "name": "superpowers-vscode-clurdra", "displayName": "Superpowers-clurdra", - "version": "0.2.130", + "version": "0.2.131", "packageManager": "pnpm@10.27.0", "description": "Superpowers specs and plans Kanban explorer", "author": "clurdra", diff --git a/vscode/src/panel/KanbanPanel.ts b/vscode/src/panel/KanbanPanel.ts index bc13e2a..ccf7a90 100644 --- a/vscode/src/panel/KanbanPanel.ts +++ b/vscode/src/panel/KanbanPanel.ts @@ -538,6 +538,10 @@ export class KanbanWebviewPanel { void issues.handleUpdateBrainstormProfilePath(this, msg.issueNumber, msg.brainstormProfilePath) return } + if (msg.type === 'issue/clear-brainstorm-session') { + void issues.handleClearBrainstormSession(this, msg.issueNumber) + return + } if (msg.type === 'issue/update-test-profile-path') { void issues.handleUpdateTestProfilePath(this, msg.issueNumber, msg.testProfilePath) return diff --git a/vscode/src/panel/handlers/issues.ts b/vscode/src/panel/handlers/issues.ts index 273a852..f7f306a 100644 --- a/vscode/src/panel/handlers/issues.ts +++ b/vscode/src/panel/handlers/issues.ts @@ -1976,6 +1976,77 @@ export async function handleUpdateProfilePath(panel: KanbanWebviewPanel, issueNu } } +/** + * 清掉工单记的头脑风暴会话 id,下次点 ▶ 续聊就新开一个会话。 + * + * 用处:旧会话的历史被 `claude --resume` 原样带回来(里面可能还留着几个版本 + * 之前的提示词和它报的错),想从干净的上下文重新聊需求时用。会话文件本身不动, + * 手上有 id 仍可用 `claude --resume ` 找回。 + */ +export async function handleClearBrainstormSession(panel: KanbanWebviewPanel, issueNumber: number): Promise { + let previousValue: string | undefined + try { + const existingState = await panel.readIssueState(issueNumber) + previousValue = typeof existingState.sessionId === 'string' ? existingState.sessionId : undefined + } + catch { + previousValue = undefined + } + + if (!previousValue) { + panel.postMessage({ + type: 'toast/show', + id: makeNonce(), + level: 'info', + message: `工单 #${issueNumber} 本来就没有头脑风暴会话`, + dismissOnTimer: 4000, + }) + return + } + + const choice = await window.showWarningMessage( + `确定清除工单 #${issueNumber} 的头脑风暴会话 id(${previousValue})?下次续聊会新开一个会话,旧会话记录还在,可用 claude --resume 找回。`, + { modal: true }, + '清除', + ) + if (choice !== '清除') + return + + try { + await panel.mergeIssueState(issueNumber, { sessionId: '' }) + } + catch (err) { + const message = err instanceof Error ? err.message : String(err) + logger.add({ + level: 'error', + source: 'panel', + message: `清除 sessionId 失败 (issue #${issueNumber})`, + details: message, + }) + panel.postMessage({ + type: 'toast/show', + id: makeNonce(), + level: 'error', + message: `清除工单 #${issueNumber} 头脑风暴会话失败: ${message}`, + dismissOnTimer: 6000, + }) + return + } + + panel.postMessage({ + type: 'issue/patch', + issueNumber, + patch: { sessionId: null }, + }) + panel.postMessage({ + type: 'toast/show', + id: makeNonce(), + level: 'success', + message: `工单 #${issueNumber} 头脑风暴会话已清除,下次续聊将新开会话`, + dismissOnTimer: 5000, + }) +} + /** * Persist a per-issue `brainstormProfilePath` override into the issue's state * JSON. Brainstorm start/resume use this profile (see resolveBrainstormProfilePath); diff --git a/vscode/src/panel/messages.ts b/vscode/src/panel/messages.ts index cbd2869..b32e2f6 100644 --- a/vscode/src/panel/messages.ts +++ b/vscode/src/panel/messages.ts @@ -213,6 +213,7 @@ export type WebviewToExtension | { type: 'issue/update-auto-review', issueNumber: number, value: boolean } | { type: 'issue/update-profile-path', issueNumber: number, profilePath: string } | { type: 'issue/update-brainstorm-profile-path', issueNumber: number, brainstormProfilePath: string } + | { type: 'issue/clear-brainstorm-session', issueNumber: number } | { type: 'issue/update-test-profile-path', issueNumber: number, testProfilePath: string } | { type: 'logs/fetch' } | { type: 'logs/clear' } diff --git a/vscode/src/panel/readOnlyGuard.ts b/vscode/src/panel/readOnlyGuard.ts index 7f5c150..d11c185 100644 --- a/vscode/src/panel/readOnlyGuard.ts +++ b/vscode/src/panel/readOnlyGuard.ts @@ -26,6 +26,7 @@ export const OWNER_ONLY_MESSAGE_TYPES: ReadonlySet = new Set([ 'issue/update-auto-review', 'issue/update-profile-path', 'issue/update-brainstorm-profile-path', + 'issue/clear-brainstorm-session', 'issue/update-test-profile-path', 'dependency/set', 'dependency/clear', diff --git a/vscode/webview-ui/src/App.tsx b/vscode/webview-ui/src/App.tsx index 8ef8070..3a3da11 100644 --- a/vscode/webview-ui/src/App.tsx +++ b/vscode/webview-ui/src/App.tsx @@ -56,6 +56,7 @@ export function App() { closeIssue, closeSessionTab, continueBrainstorm, + clearBrainstormSession, changeColumn, setDependency, clearDependency, @@ -388,6 +389,7 @@ export function App() { onResetToTodo={n => changeColumn(n, 'todo', selectedIssue?.source, selectedIssue?.externalId)} onCloseSessionTab={closeSessionTab} onContinueBrainstorm={continueBrainstorm} + onClearBrainstormSession={clearBrainstormSession} onUpdateAutoReview={updateIssueAutoReview} onUpdateProfilePath={updateIssueProfilePath} onUpdateBrainstormProfilePath={updateIssueBrainstormProfilePath} diff --git a/vscode/webview-ui/src/components/BottomTabs.tsx b/vscode/webview-ui/src/components/BottomTabs.tsx index 5f2cbe6..b4dcba5 100644 --- a/vscode/webview-ui/src/components/BottomTabs.tsx +++ b/vscode/webview-ui/src/components/BottomTabs.tsx @@ -45,6 +45,7 @@ interface BottomTabsProps { onResetToTodo: (issueNumber: number) => void onCloseSessionTab: (issueNumber: number, kind: 'brainstorm' | 'implement' | 'review' | 'test') => void onContinueBrainstorm: (issueNumber: number) => void + onClearBrainstormSession: (issueNumber: number) => void onUpdateAutoReview: (issueNumber: number, value: boolean) => void onUpdateProfilePath: (issueNumber: number, profilePath: string) => void onUpdateBrainstormProfilePath: (issueNumber: number, brainstormProfilePath: string) => void @@ -142,6 +143,7 @@ export function BottomTabs(props: BottomTabsProps) { onResetToTodo={props.onResetToTodo} onCloseSessionTab={props.onCloseSessionTab} onContinueBrainstorm={props.onContinueBrainstorm} + onClearBrainstormSession={props.onClearBrainstormSession} onUpdateAutoReview={props.onUpdateAutoReview} onUpdateProfilePath={props.onUpdateProfilePath} onUpdateBrainstormProfilePath={props.onUpdateBrainstormProfilePath} diff --git a/vscode/webview-ui/src/components/IssueDetailPanel.tsx b/vscode/webview-ui/src/components/IssueDetailPanel.tsx index 5b66fa6..49dba59 100644 --- a/vscode/webview-ui/src/components/IssueDetailPanel.tsx +++ b/vscode/webview-ui/src/components/IssueDetailPanel.tsx @@ -1,7 +1,7 @@ import type { ClaudeProfile } from '../hooks/useIssues' import type { Issue, IssueColumn } from '../types' import type { PropertyGroup, RowAction } from './property-grid' -import { ArrowRightLeft, CircleSlash, Download, ExternalLink, GitMerge, Loader2, Play, RotateCcw, Terminal, Trash2, X } from 'lucide-react' +import { ArrowRightLeft, CircleSlash, Download, Eraser, ExternalLink, GitMerge, Loader2, Play, RotateCcw, Terminal, Trash2, X } from 'lucide-react' import { useMemo, useRef } from 'react' import { isIssueLocked } from '../lib/dependencies' import { isIssueMine, issueOwnerLogin } from '../lib/issueOwnership' @@ -93,6 +93,7 @@ interface IssueDetailPanelProps { * 打进去,关了就 `claude --resume ` 带着提示词恢复,没会话就新开一个。 */ onContinueBrainstorm: (issueNumber: number) => void + onClearBrainstormSession: (issueNumber: number) => void /** Persist a per-issue `autoReview` override into the state JSON. */ onUpdateAutoReview: (issueNumber: number, value: boolean) => void /** 已知 Claude profile 列表,用于「配置文件」下拉选项。 */ @@ -144,6 +145,7 @@ export function IssueDetailPanel({ onResetToTodo, onCloseSessionTab, onContinueBrainstorm, + onClearBrainstormSession, onUpdateAutoReview, profiles, onUpdateProfilePath, @@ -236,6 +238,16 @@ export function IssueDetailPanel({ }, }) } + if (hasSession) { + secondaryActions.push({ + icon: , + title: '清除会话:下次续聊新开一个,不再带旧会话的历史', + onClick: () => { + if (issue) + onClearBrainstormSession(issue.number) + }, + }) + } return { key: 'sessionId', label: '头脑风暴会话id', @@ -523,7 +535,7 @@ export function IssueDetailPanel({ ], }, ], - [onResumeSession, onResumeReviewSession, onResumeTestSession, onStartTestSession, onOpenFile, onImplement, onOpenPr, onGeneratePrDiffSummary, onOpenWorktree, onDeleteWorktree, onMergeBranch, onCloseSessionTab, onContinueBrainstorm, onOpenLogs, issue, locked, lockTitle, globalAutoReview, prDiffSummaryRunning, profiles], + [onResumeSession, onResumeReviewSession, onResumeTestSession, onStartTestSession, onOpenFile, onImplement, onOpenPr, onGeneratePrDiffSummary, onOpenWorktree, onDeleteWorktree, onMergeBranch, onCloseSessionTab, onContinueBrainstorm, onClearBrainstormSession, onOpenLogs, issue, locked, lockTitle, globalAutoReview, prDiffSummaryRunning, profiles], ) // 同事的工单只读:属性表统一消毒,顶部只留查看类按钮。 @@ -617,7 +629,7 @@ export function IssueDetailPanel({ ) : null} - + )} - + - +