浏览代码

默认隐藏 Bot 和普通聊天的思考过程与工具

Samien 1 月之前
父节点
当前提交
34762fd

+ 1 - 1
src/client/utils/sessionPreferences.ts

@@ -23,7 +23,7 @@ export function moveSessionFastMode(userId: string, profile: string, fromSession
 }
 
 export function readAgentShowThinking(userId: string, profile: string): boolean {
-  try { return localStorage.getItem(scopedKey(THINKING_PREFIX, userId, profile)) !== '0' } catch { return true }
+  try { return localStorage.getItem(scopedKey(THINKING_PREFIX, userId, profile)) === '1' } catch { return false }
 }
 
 export function writeAgentShowThinking(userId: string, profile: string, visible: boolean): void {

+ 1 - 1
src/client/views/ChatView.vue

@@ -41,7 +41,7 @@ const mediaPreviewIndex = ref<number | null>(null)
 const outlineOpen = ref(false)
 const modelDialog = ref(false)
 const modelSwitching = ref(false)
-const showThinking = ref(true)
+const showThinking = ref(false)
 const queueMode = ref(false)
 const actionSessionId = ref('')
 const renaming = ref(false)

+ 1 - 1
src/client/views/ConversationsView.vue

@@ -108,7 +108,7 @@ const timeline = ref<InstanceType<typeof MessageTimeline>>()
 const quoted = ref<UiMessage | null>(null)
 const preview = ref<UiLibraryItem | null>(null)
 const mediaIndex = ref<number | null>(null)
-const showThinking = ref(true)
+const showThinking = ref(false)
 const transcriptStore = new WorkspaceTranscriptStore()
 const renderedMessages = new WeakMap<Message, UiMessage>()
 const uiMessages = computed(() => messages.value.filter(m => m.visible !== false).map(message => {

+ 1 - 1
src/client/views/GroupsView.vue

@@ -40,7 +40,7 @@ const router = useRouter()
 const createOpen = ref(false)
 const topicTeamPickerOpen = ref(false)
 const managerOpen = ref(false)
-const showThinking = ref(true)
+const showThinking = ref(false)
 const quoted = ref<UiMessage | null>(null)
 const preview = ref<UiLibraryItem | null>(null)
 const mediaPreviewIndex = ref<number | null>(null)

+ 1 - 1
src/client/views/HistoryView.vue

@@ -41,7 +41,7 @@ const mediaPreviewIndex = ref<number | null>(null)
 const outlineOpen = ref(false)
 const modelDialog = ref(false)
 const modelSwitching = ref(false)
-const showThinking = ref(true)
+const showThinking = ref(false)
 const queueMode = ref(false)
 const actionSessionId = ref('')
 const renaming = ref(false)

+ 14 - 4
tests/client/sessionPreferences.test.ts

@@ -1,8 +1,18 @@
-import { describe, expect, it } from 'vitest'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
 import {
   moveSessionFastMode, readAgentShowThinking, readSessionFastMode, writeAgentShowThinking, writeSessionFastMode,
 } from '@/utils/sessionPreferences'
 
+beforeEach(() => {
+  const values = new Map<string, string>()
+  vi.stubGlobal('localStorage', {
+    getItem: (key: string) => values.get(key) ?? null,
+    setItem: (key: string, value: string) => void values.set(key, value),
+    removeItem: (key: string) => void values.delete(key),
+  })
+})
+afterEach(() => vi.unstubAllGlobals())
+
 describe('session and Agent display preferences', () => {
   it('isolates fast mode by account, Agent, and session', () => {
     writeSessionFastMode('u1', 'yaoer', 's1', true)
@@ -19,11 +29,11 @@ describe('session and Agent display preferences', () => {
     expect(readSessionFastMode('u1', 'default', 'stored-1')).toBe(true)
   })
 
-  it('stores show-thinking once per account and Agent', () => {
-    expect(readAgentShowThinking('u1', 'yaoer')).toBe(true)
+  it('hides thinking by default and stores an explicit choice per account and Agent', () => {
+    expect(readAgentShowThinking('u1', 'yaoer')).toBe(false)
     writeAgentShowThinking('u1', 'yaoer', false)
     expect(readAgentShowThinking('u1', 'yaoer')).toBe(false)
-    expect(readAgentShowThinking('u1', 'default')).toBe(true)
+    expect(readAgentShowThinking('u1', 'default')).toBe(false)
     writeAgentShowThinking('u1', 'yaoer', true)
     expect(readAgentShowThinking('u1', 'yaoer')).toBe(true)
   })

+ 7 - 0
tests/e2e/workspace-chat.spec.ts

@@ -187,6 +187,9 @@ test('an idle Web viewer follows an iOS-origin run and restores thinking after r
     && response.request().postDataJSON()?.method === 'session.resume')
   await page.goto(`/chat/${session.stored_session_id}?profile=default`)
   await subscribed
+  await page.getByRole('button', { name: '设置', exact: true }).click()
+  await page.getByRole('switch', { name: /显示思考/ }).click()
+  await page.getByRole('button', { name: '设置', exact: true }).click()
   await command('prompt.submit', { session_id: session.session_id, text: '[cross-client-live] 检查文件' })
   const typing = page.getByTestId('chat-run-thinking-dots')
   await expect(typing).toBeVisible()
@@ -658,6 +661,8 @@ test('only chat messages introduce files across transcript and library', async (
   const report = page.locator('.message--assistant .file-link-card').first()
   await expect(report).toBeVisible()
   const process = page.locator('.turn-trace')
+  await expect(process).toHaveCount(0)
+  await page.locator('.composer-tool[title="显示思考"]').click()
   await expect(process).toHaveCount(1)
   await process.locator('summary').first().click()
   await expect(process).toContainText('/tmp/process.pdf')
@@ -671,6 +676,8 @@ test('only chat messages introduce files across transcript and library', async (
   await preview.getByRole('button', { name: '关闭预览' }).click()
   await page.reload()
   await expect(page.locator('.message--assistant .file-link-card')).toHaveCount(1)
+  await expect(page.locator('.turn-trace')).toHaveCount(0)
+  await page.locator('.composer-tool[title="显示思考"]').click()
   await page.locator('.turn-trace summary').first().click()
   await page.setViewportSize({ width: 1280, height: 1100 })
   await page.screenshot({ path: testInfo.outputPath('message-files-web.png') })

+ 12 - 6
tests/e2e/workspace.spec.ts

@@ -586,17 +586,17 @@ test('reconciles an iOS fast-mode selection from the resumed 9119 session', asyn
 
 test('keeps the show-thinking preference across sessions of the same Agent', async ({ page }) => {
   await page.goto('/chat/session-demo')
-  await expect(page.locator('.turn-trace')).toHaveCount(1)
+  await expect(page.locator('.turn-trace')).toHaveCount(0)
   await page.locator('.composer-tool[aria-label="设置"]').click()
   const setting = page.getByRole('switch', { name: /显示思考/ })
-  await expect(setting).toHaveAttribute('aria-checked', 'true')
+  await expect(setting).toHaveAttribute('aria-checked', 'false')
   await setting.click()
-  await expect(page.locator('.turn-trace')).toHaveCount(0)
+  await expect(page.locator('.turn-trace')).toHaveCount(1)
   await openSecondSession(page)
-  await expect(page.locator('.turn-trace')).toHaveCount(0)
+  await expect(page.locator('.turn-trace')).toHaveCount(1)
   await page.locator('.composer-tool[aria-label="设置"]').click()
   await page.getByRole('switch', { name: /显示思考/ }).click()
-  await expect(page.locator('.turn-trace')).toHaveCount(1)
+  await expect(page.locator('.turn-trace')).toHaveCount(0)
 })
 
 test('restores a legacy session link under its owning Agent profile', async ({ page }) => {
@@ -729,6 +729,9 @@ test('renders persisted user image markers as direct images instead of file card
 
 test('folds tool result rows into their expandable tool call', async ({ page }) => {
   await page.goto('/chat/session-demo')
+  await page.getByRole('button', { name: '设置', exact: true }).click()
+  await page.getByRole('switch', { name: /显示思考/ }).click()
+  await page.getByRole('button', { name: '设置', exact: true }).click()
   const trace = page.locator('.turn-trace').first()
   await expect(trace).not.toHaveAttribute('open', '')
   await expect(trace).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)')
@@ -870,6 +873,9 @@ test.skip('uses HTTP commands and SSE for chat and team events without opening c
 
 test('keeps streamed text below sealed interim commentary and its tool trace', async ({ page }) => {
   await page.goto('/chat/session-demo?profile=yaoyao')
+  await page.getByRole('button', { name: '设置', exact: true }).click()
+  await page.getByRole('switch', { name: /显示思考/ }).click()
+  await page.getByRole('button', { name: '设置', exact: true }).click()
   await page.locator('.composer-textarea').fill('验证流式分段')
   await page.getByRole('button', { name: '发送消息' }).click()
 
@@ -916,7 +922,7 @@ test('keeps the canonical logo and yaoyao-webui composer geometry', async ({ pag
   await expect(assistantMessage.locator('.message__actions')).toHaveCSS('opacity', '1')
   await expect(page.locator('.message--tool-only .message__actions')).toHaveCount(0)
   await expect(page.locator('[data-message-id="message-thinking-tool"]')).toHaveCount(0)
-  await expect(page.locator('.turn-trace').first()).toBeVisible()
+  await expect(page.locator('.turn-trace')).toHaveCount(0)
   const userMessageMeta = page.locator('.message--user .message__meta')
   await expect(userMessageMeta).not.toHaveCount(0)
   expect(await userMessageMeta.evaluateAll(elements => elements.every(element => getComputedStyle(element).display === 'none'))).toBe(true)