✨ feat(vscode): 问 AI 输入框旁边能选 Claude profile,记住上次选的,问答灰字写用哪个 profile 答的

This commit is contained in:
cruldra committed 2026-09-26 22:28:29 +08:00
1 parent 1eb42d8389
commit 9efae1f496
20 files changed
+397 -63

No files matched your search

+26 -6
View File
@@ -1,8 +1,9 @@
import type { KeyboardEvent, ReactElement } from 'react'
import type { Ask } from './qa'
import type { QaEntryView } from './types'
import type { ProfileChoice, QaEntryView } from './types'
import { ChevronDown, ChevronRight, CircleStop, LoaderCircle, SendHorizontal, Sparkles, Trash2, TriangleAlert } from 'lucide-react'
import { useState } from 'react'
import { SelectMenu } from '@/components/ui/select-menu'
import { renderMarkdown, renderMarkdownOnce } from './markdown'
import { answerPreview, relativeTime } from './qa'
@@ -17,9 +18,12 @@ function HistoryItem({ entry, now, onDelete }: { entry: QaEntryView, now: number
<button type="button" className="cr-qa-question" aria-expanded={expanded} title={expanded ? '收起回答' : '展开整段回答'} onClick={toggle}>
{entry.question}
</button>
<time className="cr-qa-when" dateTime={entry.createdAt} title={new Date(entry.createdAt).toLocaleString()}>
{relativeTime(entry.createdAt, now)}
</time>
<span className="cr-qa-when">
<time dateTime={entry.createdAt} title={new Date(entry.createdAt).toLocaleString()}>
{relativeTime(entry.createdAt, now)}
</time>
{entry.profile && <span title="用这个 Claude Code 配置(profile)答的">{` · ${entry.profile}`}</span>}
</span>
<button type="button" className="cr-tool cr-qa-delete" title="已理解,删除" aria-label="已理解,删除" onClick={onDelete}>
<Trash2 size={13} strokeWidth={1.8} aria-hidden />
</button>
@@ -69,10 +73,12 @@ function CurrentItem({ ask }: { ask: Ask }): ReactElement {
}
/** 底下的输入框:Enter 发送、Shift+Enter 换行、Esc 收起;正在答时发送换成停止 */
function AskInput({ running, first, onAsk, onStop, onClose }: {
function AskInput({ running, first, profiles, onSelectProfile, onAsk, onStop, onClose }: {
running: Ask | undefined
/** 这块还没问过:提示「问这块代码…」,问过了是「继续问…」 */
first: boolean
profiles: ProfileChoice
onSelectProfile: (id: string) => void
onAsk: (question: string) => void
onStop: (askId: string) => void
onClose: () => void
@@ -107,6 +113,15 @@ function AskInput({ running, first, onAsk, onStop, onClose }: {
onChange={event => setValue(event.target.value)}
onKeyDown={onKeyDown}
/>
<SelectMenu
variant="ghost"
value={profiles.selected}
options={profiles.options.map(option => ({ value: option.id, label: option.label }))}
onChange={onSelectProfile}
placeholder="默认"
title="用哪个 Claude Code 配置(profile)回答,下一个问题起用它"
className="cr-qa-profile"
/>
{running
? (
<button type="button" className="cr-tool" title="停止" aria-label="停止" onClick={() => onStop(running.askId)}>
@@ -127,7 +142,10 @@ export interface AskThreadProps {
asks: Ask[]
/** 点了「问 AI」:展开全部历史、当前这一轮和输入框 */
open: boolean
/** 输入框旁边的 profile 下拉 */
profiles: ProfileChoice
now?: number
onSelectProfile: (id: string) => void
onAsk: (question: string) => void
onStop: (askId: string) => void
onDelete: (entryId: string) => void
@@ -138,7 +156,7 @@ export interface AskThreadProps {
* 块下面的问答区(左边一条竖线):展开时是灰字的历史、当前这一轮、输入框;
* 没展开但问过的块只露一行「问过 N 次」,点开看灰字历史,读代码时一眼知道这里问过什么。
*/
export function AskThread({ history, asks, open, now = Date.now(), onAsk, onStop, onDelete, onClose }: AskThreadProps): ReactElement | null {
export function AskThread({ history, asks, open, profiles, now = Date.now(), onSelectProfile, onAsk, onStop, onDelete, onClose }: AskThreadProps): ReactElement | null {
const [showHistory, setShowHistory] = useState(false)
if (!open) {
if (history.length === 0)
@@ -163,6 +181,8 @@ export function AskThread({ history, asks, open, now = Date.now(), onAsk, onStop
<AskInput
running={asks.find(ask => ask.status === 'running')}
first={history.length === 0 && asks.length === 0}
profiles={profiles}
onSelectProfile={onSelectProfile}
onAsk={onAsk}
onStop={onStop}
onClose={onClose}