mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-20 13:53:32 +08:00
Merge AskUserQuestion multi-select fix into main
The detached desktop bugfix worktree contains the AskUserQuestion multi-select handling change, while local main already carries separate local commits. Merge instead of cherry-picking so main records the worktree integration point without dropping local-only history. Constraint: Local main and the detached worktree had diverged Rejected: Reset main to the worktree HEAD | would discard local main commits Confidence: high Scope-risk: narrow Directive: Keep AskUserQuestion selection mode controlled by the explicit multiSelect marker Tested: cd desktop && bun run test -- src/components/chat/AskUserQuestion.test.tsx src/components/chat/chatBlocks.test.tsx src/components/chat/MessageList.test.tsx Tested: bun run check:desktop Not-tested: Full root bun run verify after merge
This commit is contained in:
commit
184323ba02
@ -108,4 +108,156 @@ describe('AskUserQuestion', () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('allows multiple selections when a question is marked multiSelect', () => {
|
||||||
|
render(
|
||||||
|
<AskUserQuestion
|
||||||
|
toolUseId="tool-1"
|
||||||
|
input={{
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
question: 'Which tasks should run?',
|
||||||
|
multiSelect: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Lint' },
|
||||||
|
{ label: 'Tests' },
|
||||||
|
{ label: 'Build' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /^Lint$/ }))
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /^Tests$/ }))
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /submit/i }))
|
||||||
|
|
||||||
|
expect(sendMock).toHaveBeenCalledWith(ACTIVE_TAB, {
|
||||||
|
type: 'permission_response',
|
||||||
|
requestId: 'perm-1',
|
||||||
|
allowed: true,
|
||||||
|
updatedInput: {
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
question: 'Which tasks should run?',
|
||||||
|
multiSelect: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Lint' },
|
||||||
|
{ label: 'Tests' },
|
||||||
|
{ label: 'Build' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
answers: {
|
||||||
|
'Which tasks should run?': 'Lint, Tests',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('preserves multiSelect for single-question input shape', () => {
|
||||||
|
render(
|
||||||
|
<AskUserQuestion
|
||||||
|
toolUseId="tool-1"
|
||||||
|
input={{
|
||||||
|
question: 'Which tasks should run?',
|
||||||
|
multiSelect: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Lint' },
|
||||||
|
{ label: 'Tests' },
|
||||||
|
{ label: 'Build' },
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /^Lint$/ }))
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /^Tests$/ }))
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /submit/i }))
|
||||||
|
|
||||||
|
expect(sendMock).toHaveBeenCalledWith(ACTIVE_TAB, {
|
||||||
|
type: 'permission_response',
|
||||||
|
requestId: 'perm-1',
|
||||||
|
allowed: true,
|
||||||
|
updatedInput: {
|
||||||
|
question: 'Which tasks should run?',
|
||||||
|
multiSelect: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Lint' },
|
||||||
|
{ label: 'Tests' },
|
||||||
|
{ label: 'Build' },
|
||||||
|
],
|
||||||
|
answers: {
|
||||||
|
'Which tasks should run?': 'Lint, Tests',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('responds to the provided session instead of the active tab', () => {
|
||||||
|
useTabStore.setState({
|
||||||
|
activeTabId: 'other-tab',
|
||||||
|
tabs: [
|
||||||
|
{ sessionId: 'other-tab', title: 'Other', type: 'session', status: 'idle' },
|
||||||
|
{ sessionId: 'target-tab', title: 'Target', type: 'session', status: 'idle' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
useChatStore.setState((state) => ({
|
||||||
|
sessions: {
|
||||||
|
...state.sessions,
|
||||||
|
'target-tab': {
|
||||||
|
...state.sessions[ACTIVE_TAB]!,
|
||||||
|
pendingPermission: {
|
||||||
|
requestId: 'perm-target',
|
||||||
|
toolName: 'AskUserQuestion',
|
||||||
|
toolUseId: 'tool-target',
|
||||||
|
input: {
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
question: 'Run tests?',
|
||||||
|
options: [{ label: 'No' }, { label: 'Yes' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
render(
|
||||||
|
<AskUserQuestion
|
||||||
|
sessionId="target-tab"
|
||||||
|
toolUseId="tool-target"
|
||||||
|
input={{
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
question: 'Run tests?',
|
||||||
|
options: [{ label: 'No' }, { label: 'Yes' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /^Yes$/ }))
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: /submit/i }))
|
||||||
|
|
||||||
|
expect(sendMock).toHaveBeenCalledWith('target-tab', {
|
||||||
|
type: 'permission_response',
|
||||||
|
requestId: 'perm-target',
|
||||||
|
allowed: true,
|
||||||
|
updatedInput: {
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
question: 'Run tests?',
|
||||||
|
options: [{ label: 'No' }, { label: 'Yes' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
answers: {
|
||||||
|
'Run tests?': 'Yes',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -13,15 +13,19 @@ type Question = {
|
|||||||
question: string
|
question: string
|
||||||
header?: string
|
header?: string
|
||||||
options?: QuestionOption[]
|
options?: QuestionOption[]
|
||||||
|
multiSelect?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type AskUserInput = {
|
type AskUserInput = {
|
||||||
questions?: Question[]
|
questions?: Question[]
|
||||||
question?: string
|
question?: string
|
||||||
|
header?: string
|
||||||
options?: QuestionOption[]
|
options?: QuestionOption[]
|
||||||
|
multiSelect?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
sessionId?: string | null
|
||||||
toolUseId: string
|
toolUseId: string
|
||||||
input: unknown
|
input: unknown
|
||||||
result?: unknown
|
result?: unknown
|
||||||
@ -41,21 +45,34 @@ function parseInput(input: unknown): Question[] {
|
|||||||
|
|
||||||
// Shape 2: { question: "...", options: [...] }
|
// Shape 2: { question: "...", options: [...] }
|
||||||
if (typeof obj.question === 'string') {
|
if (typeof obj.question === 'string') {
|
||||||
return [{ question: obj.question, options: obj.options }]
|
return [{
|
||||||
|
question: obj.question,
|
||||||
|
header: obj.header,
|
||||||
|
options: obj.options,
|
||||||
|
multiSelect: obj.multiSelect,
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AskUserQuestion({ toolUseId, input, result }: Props) {
|
type QuestionSelections = Record<number, string[]>
|
||||||
|
|
||||||
|
function getSelectedAnswer(question: Question, selected: string[] | undefined) {
|
||||||
|
if (!selected || selected.length === 0) return ''
|
||||||
|
return question.multiSelect ? selected.join(', ') : selected[0] ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AskUserQuestion({ sessionId, toolUseId, input, result }: Props) {
|
||||||
const { respondToPermission } = useChatStore()
|
const { respondToPermission } = useChatStore()
|
||||||
const activeTabId = useTabStore((s) => s.activeTabId)
|
const activeTabId = useTabStore((s) => s.activeTabId)
|
||||||
const pendingPermission = useChatStore((s) => activeTabId ? s.sessions[activeTabId]?.pendingPermission : undefined)
|
const targetSessionId = sessionId ?? activeTabId
|
||||||
|
const pendingPermission = useChatStore((s) => targetSessionId ? s.sessions[targetSessionId]?.pendingPermission : undefined)
|
||||||
const t = useTranslation()
|
const t = useTranslation()
|
||||||
const questions = parseInput(input)
|
const questions = parseInput(input)
|
||||||
const inputObject = (input && typeof input === 'object') ? input as Record<string, unknown> : {}
|
const inputObject = (input && typeof input === 'object') ? input as Record<string, unknown> : {}
|
||||||
const [activeTab, setActiveTab] = useState(0)
|
const [activeTab, setActiveTab] = useState(0)
|
||||||
const [selections, setSelections] = useState<Record<number, string>>({})
|
const [selections, setSelections] = useState<QuestionSelections>({})
|
||||||
const [freeText, setFreeText] = useState('')
|
const [freeText, setFreeText] = useState('')
|
||||||
const [hasSubmitted, setHasSubmitted] = useState(false)
|
const [hasSubmitted, setHasSubmitted] = useState(false)
|
||||||
const composingRef = useRef(false)
|
const composingRef = useRef(false)
|
||||||
@ -78,20 +95,36 @@ export function AskUserQuestion({ toolUseId, input, result }: Props) {
|
|||||||
.filter((answer): answer is string => typeof answer === 'string' && answer.trim().length > 0)
|
.filter((answer): answer is string => typeof answer === 'string' && answer.trim().length > 0)
|
||||||
.join(', ')
|
.join(', ')
|
||||||
}
|
}
|
||||||
return freeText.trim() || Object.values(selections).join(', ')
|
return freeText.trim() || questions
|
||||||
|
.map((question, index) => getSelectedAnswer(question, selections[index]))
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('; ')
|
||||||
}, [freeText, questions, resultAnswers, selections])
|
}, [freeText, questions, resultAnswers, selections])
|
||||||
const submitted = Object.keys(resultAnswers).length > 0 || hasSubmitted
|
const submitted = Object.keys(resultAnswers).length > 0 || hasSubmitted
|
||||||
|
|
||||||
const handleSelect = (qIndex: number, label: string) => {
|
const handleSelect = (qIndex: number, label: string) => {
|
||||||
if (submitted) return
|
if (submitted) return
|
||||||
setSelections((prev) => {
|
setSelections((prev) => {
|
||||||
// Toggle: deselect if already selected
|
const question = questions[qIndex]
|
||||||
if (prev[qIndex] === label) {
|
const selected = prev[qIndex] ?? []
|
||||||
|
if (question?.multiSelect) {
|
||||||
|
const nextSelected = selected.includes(label)
|
||||||
|
? selected.filter((value) => value !== label)
|
||||||
|
: [...selected, label]
|
||||||
|
const next = { ...prev }
|
||||||
|
if (nextSelected.length > 0) {
|
||||||
|
next[qIndex] = nextSelected
|
||||||
|
} else {
|
||||||
|
delete next[qIndex]
|
||||||
|
}
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
if (selected[0] === label) {
|
||||||
const next = { ...prev }
|
const next = { ...prev }
|
||||||
delete next[qIndex]
|
delete next[qIndex]
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
return { ...prev, [qIndex]: label }
|
return { ...prev, [qIndex]: [label] }
|
||||||
})
|
})
|
||||||
setFreeText('')
|
setFreeText('')
|
||||||
}
|
}
|
||||||
@ -101,25 +134,26 @@ export function AskUserQuestion({ toolUseId, input, result }: Props) {
|
|||||||
|
|
||||||
const parts: string[] = []
|
const parts: string[] = []
|
||||||
for (let i = 0; i < questions.length; i++) {
|
for (let i = 0; i < questions.length; i++) {
|
||||||
const selected = selections[i]
|
const selected = getSelectedAnswer(questions[i]!, selections[i])
|
||||||
if (selected) parts.push(selected)
|
if (selected) parts.push(selected)
|
||||||
}
|
}
|
||||||
const response = freeText.trim() || parts.join('; ') || ''
|
const response = freeText.trim() || parts.join('; ') || ''
|
||||||
if (!response) return
|
if (!response) return
|
||||||
|
|
||||||
if (!activeTabId || !pendingRequest) return
|
if (!targetSessionId || !pendingRequest) return
|
||||||
|
|
||||||
const answers = questions.reduce<Record<string, string>>((acc, question, index) => {
|
const answers = questions.reduce<Record<string, string>>((acc, question, index) => {
|
||||||
if (freeText.trim()) {
|
if (freeText.trim()) {
|
||||||
acc[question.question] = freeText.trim()
|
acc[question.question] = freeText.trim()
|
||||||
} else if (selections[index]) {
|
} else {
|
||||||
acc[question.question] = selections[index]!
|
const selected = getSelectedAnswer(question, selections[index])
|
||||||
|
if (selected) acc[question.question] = selected
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
setHasSubmitted(true)
|
setHasSubmitted(true)
|
||||||
respondToPermission(activeTabId, pendingRequest.requestId, true, {
|
respondToPermission(targetSessionId, pendingRequest.requestId, true, {
|
||||||
updatedInput: {
|
updatedInput: {
|
||||||
...inputObject,
|
...inputObject,
|
||||||
answers,
|
answers,
|
||||||
@ -128,7 +162,7 @@ export function AskUserQuestion({ toolUseId, input, result }: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All questions must be answered (via selection or free text) to enable submit
|
// All questions must be answered (via selection or free text) to enable submit
|
||||||
const allAnswered = freeText.trim().length > 0 || questions.every((_, i) => selections[i] !== undefined)
|
const allAnswered = freeText.trim().length > 0 || questions.every((_, i) => (selections[i]?.length ?? 0) > 0)
|
||||||
const safeActiveTab = Math.min(activeTab, questions.length - 1)
|
const safeActiveTab = Math.min(activeTab, questions.length - 1)
|
||||||
const activeQuestion = questions[safeActiveTab]
|
const activeQuestion = questions[safeActiveTab]
|
||||||
|
|
||||||
@ -168,7 +202,7 @@ export function AskUserQuestion({ toolUseId, input, result }: Props) {
|
|||||||
<div className="flex px-4 border-b border-[var(--color-outline-variant)]/20 bg-[var(--color-surface-container-low)] overflow-x-auto">
|
<div className="flex px-4 border-b border-[var(--color-outline-variant)]/20 bg-[var(--color-surface-container-low)] overflow-x-auto">
|
||||||
{questions.map((q, i) => {
|
{questions.map((q, i) => {
|
||||||
const isActive = safeActiveTab === i
|
const isActive = safeActiveTab === i
|
||||||
const isAnswered = selections[i] !== undefined
|
const isAnswered = (selections[i]?.length ?? 0) > 0
|
||||||
const tabLabel = q.header || `Q${i + 1}`
|
const tabLabel = q.header || `Q${i + 1}`
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
@ -203,7 +237,8 @@ export function AskUserQuestion({ toolUseId, input, result }: Props) {
|
|||||||
{activeQuestion.options && activeQuestion.options.length > 0 && (
|
{activeQuestion.options && activeQuestion.options.length > 0 && (
|
||||||
<div className="space-y-2 mb-3">
|
<div className="space-y-2 mb-3">
|
||||||
{activeQuestion.options.map((opt, optIndex) => {
|
{activeQuestion.options.map((opt, optIndex) => {
|
||||||
const isSelected = selections[activeTab] === opt.label
|
const isSelected = selections[safeActiveTab]?.includes(opt.label) ?? false
|
||||||
|
const isMultiSelect = activeQuestion.multiSelect === true
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={optIndex}
|
key={optIndex}
|
||||||
@ -216,12 +251,12 @@ export function AskUserQuestion({ toolUseId, input, result }: Props) {
|
|||||||
} ${submitted ? 'cursor-default' : ''}`}
|
} ${submitted ? 'cursor-default' : ''}`}
|
||||||
>
|
>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
{/* Check indicator */}
|
{/* Selection indicator */}
|
||||||
<div className={`mt-0.5 flex-shrink-0 w-4 h-4 rounded-full border-2 flex items-center justify-center transition-colors ${
|
<div className={`mt-0.5 flex-shrink-0 w-4 h-4 rounded-full border-2 flex items-center justify-center transition-colors ${
|
||||||
isSelected
|
isSelected
|
||||||
? 'border-[var(--color-secondary)] bg-[var(--color-secondary)]'
|
? 'border-[var(--color-secondary)] bg-[var(--color-secondary)]'
|
||||||
: 'border-[var(--color-outline)]'
|
: 'border-[var(--color-outline)]'
|
||||||
}`}>
|
} ${isMultiSelect ? 'rounded-[var(--radius-xs)]' : 'rounded-full'}`}>
|
||||||
{isSelected && (
|
{isSelected && (
|
||||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
|
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
|
||||||
<polyline points="20 6 9 17 4 12" />
|
<polyline points="20 6 9 17 4 12" />
|
||||||
|
|||||||
@ -470,6 +470,7 @@ export function MessageList({ sessionId, compact = false }: MessageListProps = {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<MessageBlock
|
<MessageBlock
|
||||||
|
sessionId={resolvedSessionId}
|
||||||
message={item.message}
|
message={item.message}
|
||||||
activeThinkingId={activeThinkingId}
|
activeThinkingId={activeThinkingId}
|
||||||
agentTaskNotifications={agentTaskNotifications}
|
agentTaskNotifications={agentTaskNotifications}
|
||||||
@ -550,11 +551,13 @@ export function MessageList({ sessionId, compact = false }: MessageListProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MessageBlock = memo(function MessageBlock({
|
export const MessageBlock = memo(function MessageBlock({
|
||||||
|
sessionId,
|
||||||
message,
|
message,
|
||||||
activeThinkingId,
|
activeThinkingId,
|
||||||
agentTaskNotifications,
|
agentTaskNotifications,
|
||||||
toolResult,
|
toolResult,
|
||||||
}: {
|
}: {
|
||||||
|
sessionId?: string | null
|
||||||
message: UIMessage
|
message: UIMessage
|
||||||
activeThinkingId: string | null
|
activeThinkingId: string | null
|
||||||
agentTaskNotifications: Record<string, AgentTaskNotification>
|
agentTaskNotifications: Record<string, AgentTaskNotification>
|
||||||
@ -578,6 +581,7 @@ export const MessageBlock = memo(function MessageBlock({
|
|||||||
if (message.toolName === 'AskUserQuestion') {
|
if (message.toolName === 'AskUserQuestion') {
|
||||||
return (
|
return (
|
||||||
<AskUserQuestion
|
<AskUserQuestion
|
||||||
|
sessionId={sessionId}
|
||||||
toolUseId={message.toolUseId}
|
toolUseId={message.toolUseId}
|
||||||
input={message.input}
|
input={message.input}
|
||||||
result={toolResult?.content}
|
result={toolResult?.content}
|
||||||
@ -607,6 +611,7 @@ export const MessageBlock = memo(function MessageBlock({
|
|||||||
case 'permission_request':
|
case 'permission_request':
|
||||||
return (
|
return (
|
||||||
<PermissionDialog
|
<PermissionDialog
|
||||||
|
sessionId={sessionId}
|
||||||
requestId={message.requestId}
|
requestId={message.requestId}
|
||||||
toolName={message.toolName}
|
toolName={message.toolName}
|
||||||
input={message.input}
|
input={message.input}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { Button } from '../shared/Button'
|
|||||||
import { DiffViewer } from './DiffViewer'
|
import { DiffViewer } from './DiffViewer'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
sessionId?: string | null
|
||||||
requestId: string
|
requestId: string
|
||||||
toolName: string
|
toolName: string
|
||||||
input: unknown
|
input: unknown
|
||||||
@ -111,10 +112,11 @@ function renderPermissionPreview(toolName: string, input: unknown) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PermissionDialog({ requestId, toolName, input, description }: Props) {
|
export function PermissionDialog({ sessionId, requestId, toolName, input, description }: Props) {
|
||||||
const { respondToPermission } = useChatStore()
|
const { respondToPermission } = useChatStore()
|
||||||
const activeTabId = useTabStore((s) => s.activeTabId)
|
const activeTabId = useTabStore((s) => s.activeTabId)
|
||||||
const pendingPermission = useChatStore((s) => activeTabId ? s.sessions[activeTabId]?.pendingPermission : undefined)
|
const targetSessionId = sessionId ?? activeTabId
|
||||||
|
const pendingPermission = useChatStore((s) => targetSessionId ? s.sessions[targetSessionId]?.pendingPermission : undefined)
|
||||||
const t = useTranslation()
|
const t = useTranslation()
|
||||||
const isPending = pendingPermission?.requestId === requestId
|
const isPending = pendingPermission?.requestId === requestId
|
||||||
const [showRaw, setShowRaw] = useState(false)
|
const [showRaw, setShowRaw] = useState(false)
|
||||||
@ -227,7 +229,7 @@ export function PermissionDialog({ requestId, toolName, input, description }: Pr
|
|||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => activeTabId && respondToPermission(activeTabId, requestId, true)}
|
onClick={() => targetSessionId && respondToPermission(targetSessionId, requestId, true)}
|
||||||
icon={
|
icon={
|
||||||
<span className="material-symbols-outlined text-[14px]">check</span>
|
<span className="material-symbols-outlined text-[14px]">check</span>
|
||||||
}
|
}
|
||||||
@ -237,7 +239,7 @@ export function PermissionDialog({ requestId, toolName, input, description }: Pr
|
|||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => activeTabId && respondToPermission(activeTabId, requestId, true, { rule: 'always' })}
|
onClick={() => targetSessionId && respondToPermission(targetSessionId, requestId, true, { rule: 'always' })}
|
||||||
icon={
|
icon={
|
||||||
<span className="material-symbols-outlined text-[14px]">verified</span>
|
<span className="material-symbols-outlined text-[14px]">verified</span>
|
||||||
}
|
}
|
||||||
@ -248,7 +250,7 @@ export function PermissionDialog({ requestId, toolName, input, description }: Pr
|
|||||||
<Button
|
<Button
|
||||||
variant="danger"
|
variant="danger"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => activeTabId && respondToPermission(activeTabId, requestId, false)}
|
onClick={() => targetSessionId && respondToPermission(targetSessionId, requestId, false)}
|
||||||
icon={
|
icon={
|
||||||
<span className="material-symbols-outlined text-[14px]">close</span>
|
<span className="material-symbols-outlined text-[14px]">close</span>
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user