refactor(mobile): group native chat tool transcript modules (#34399)

This commit is contained in:
Neil
2026-10-27 04:42:12 -07:00
committed by GitHub
parent d69d16a3fa
commit 532dc7f240
17 changed files with 78 additions and 72 deletions
@@ -16,7 +16,10 @@ import { MobileSourceCopyButton } from '../components/MobileSourceCopyButton'
import { colors } from '../theme/mobile-theme'
import { useMobileNativeChatOpenedDetail } from './mobile-native-chat-opened-detail'
import { useMobileNativeChatDisclosure } from './mobile-native-chat-disclosure-store'
import { toolStyles as styles, toolType } from './mobile-native-chat-tool-styles'
import {
toolStyles as styles,
toolType
} from './native-chat/transcript/mobile-native-chat-tool-styles'
function baseName(path: string): string {
return path.split(/[\\/]/).at(-1) || path
@@ -14,7 +14,7 @@ import type {
} from '../../../src/shared/agent-session-journal-types'
import { INLINE_TEXT_SELECTION } from '../components/inline-text-selection'
import { styles } from './mobile-native-chat-message-styles'
import { toolStyles } from './mobile-native-chat-tool-styles'
import { toolStyles } from './native-chat/transcript/mobile-native-chat-tool-styles'
import { MobileNativeChatOwnedScrollView } from './MobileNativeChatOwnedScrollView'
import {
MobileNativeChatItemSourceContext,
@@ -25,7 +25,7 @@ vi.mock('./MobileNativeChatMessageActionsSheet', () => ({
}))
vi.mock('./MobileNativeChatReasoningRow', () => ({ MobileNativeChatReasoningRow: 'Reasoning' }))
vi.mock('./MobileNativeChatTurnStatus', () => ({ MobileNativeChatTurnStatus: 'TurnStatus' }))
vi.mock('./MobileNativeChatToolRun', () => ({ ToolRun: 'ToolRun' }))
vi.mock('./native-chat/transcript/MobileNativeChatToolRun', () => ({ ToolRun: 'ToolRun' }))
import { MobileNativeChatMessage } from './MobileNativeChatMessage'
import { MobileNativeChatLongPressContent } from './MobileNativeChatLongPressContent'
@@ -32,7 +32,7 @@ vi.mock('./MobileNativeChatMessageActionsSheet', () => ({
}))
vi.mock('./MobileNativeChatReasoningRow', () => ({ MobileNativeChatReasoningRow: 'Reasoning' }))
vi.mock('./MobileNativeChatTurnStatus', () => ({ MobileNativeChatTurnStatus: 'TurnStatus' }))
vi.mock('./MobileNativeChatToolRun', () => ({ ToolRun: 'ToolRun' }))
vi.mock('./native-chat/transcript/MobileNativeChatToolRun', () => ({ ToolRun: 'ToolRun' }))
import { MobileNativeChatMessage } from './MobileNativeChatMessage'
@@ -40,8 +40,8 @@ import {
nativeChatAskRunSubject
} from '../../../src/shared/native-chat/input/native-chat-ask-row'
import type { NativeChatResolvedPrompt } from '../../../src/shared/native-chat-resolution-receipt'
import { MobileNativeChatSubagentGroup } from './MobileNativeChatSubagentGroup'
import { ToolRun } from './MobileNativeChatToolRun'
import { MobileNativeChatSubagentGroup } from './native-chat/transcript/MobileNativeChatSubagentGroup'
import { ToolRun } from './native-chat/transcript/MobileNativeChatToolRun'
import type { NativeChatTurnStatus } from './use-mobile-native-chat-turn-status'
import { styles } from './mobile-native-chat-message-styles'
import { agentMessageAttribution } from './mobile-agent-message-attribution'
@@ -18,7 +18,7 @@ import {
mobileNativeChatRowId
} from './mobile-native-chat-reading-place'
import { MobileNativeChatPageList } from './MobileNativeChatPageList'
import { ToolRun } from './MobileNativeChatToolRun'
import { ToolRun } from './native-chat/transcript/MobileNativeChatToolRun'
import { useMobileNativeChatTurnDisclosure } from './use-mobile-native-chat-turn-disclosure'
const platform = vi.hoisted(() => ({ OS: 'web' }))
@@ -65,7 +65,7 @@ vi.mock('lucide-react-native', () => {
const rest = ['MessageSquareMore', 'Pencil', 'Plug', 'Search', 'SquareTerminal', 'Wrench']
return Object.fromEntries([...names, ...more, ...rest].map((name) => [name, icon]))
})
vi.mock('./mobile-native-chat-tool-styles', () => ({
vi.mock('./native-chat/transcript/mobile-native-chat-tool-styles', () => ({
toolStyles: {},
toolType: () => ({ row: {}, meta: {}, code: {} })
}))
@@ -10,7 +10,7 @@ import {
} from '../../../../../src/shared/native-chat/input/native-chat-task-list'
import { colors } from '../../../theme/mobile-theme'
import { useMobileNativeChatOpenedDetail } from '../../mobile-native-chat-opened-detail'
import { toolStyles as styles, toolType } from '../../mobile-native-chat-tool-styles'
import { toolStyles as styles, toolType } from '../transcript/mobile-native-chat-tool-styles'
import { useMobileNativeChatDisclosure } from '../../mobile-native-chat-disclosure-store'
const STATUS_WORD: Record<NativeChatTask['status'], string> = {
@@ -5,15 +5,15 @@ import {
nativeChatSubagentGroupHeader,
sayNativeChatSubagentGroupEnglish as say,
subagentStateLabel
} from '../../../src/shared/native-chat-subagent-group-header'
import { normalizeSubagentState } from '../../../src/shared/native-chat-subagent-summary'
import { formatNativeChatDuration } from '../../../src/shared/native-chat-turn-status'
} from '../../../../../src/shared/native-chat-subagent-group-header'
import { normalizeSubagentState } from '../../../../../src/shared/native-chat-subagent-summary'
import { formatNativeChatDuration } from '../../../../../src/shared/native-chat-turn-status'
import type {
NativeChatSubagentGroupBlock,
NativeChatSubagentState
} from '../../../src/shared/native-chat-types'
import { useNow } from '../hooks/use-now'
import { colors, spacing, typography } from '../theme/mobile-theme'
} from '../../../../../src/shared/native-chat-types'
import { useNow } from '../../../hooks/use-now'
import { colors, spacing, typography } from '../../../theme/mobile-theme'
function stateDotStyle(state: NativeChatSubagentState): ViewStyle {
switch (state) {
@@ -13,7 +13,7 @@ import {
Wrench,
type LucideIcon
} from 'lucide-react-native'
import type { NativeChatToolIconName } from '../../../src/shared/native-chat/tools/native-chat-tool-icon'
import type { NativeChatToolIconName } from '../../../../../src/shared/native-chat/tools/native-chat-tool-icon'
const GLYPHS: Record<NativeChatToolIconName, LucideIcon> = {
eye: Eye,
@@ -1,38 +1,38 @@
import { useMemo } from 'react'
import { Pressable, Text, View } from 'react-native'
import { MobileNativeChatOwnedScrollView } from './MobileNativeChatOwnedScrollView'
import { MobileNativeChatOwnedScrollView } from '../../MobileNativeChatOwnedScrollView'
import { ChevronRight } from 'lucide-react-native'
import { agentJournalToolCallLifecycle } from '../../../src/shared/agent-journal-tool-call-lifecycle'
import { agentJournalToolCallLifecycle } from '../../../../../src/shared/agent-journal-tool-call-lifecycle'
import {
diffFromText,
diffFromToolCall
} from '../../../src/shared/native-chat/tools/native-chat-diff'
import type { NativeChatDiffLine } from '../../../src/shared/native-chat/tools/native-chat-diff'
} from '../../../../../src/shared/native-chat/tools/native-chat-diff'
import type { NativeChatDiffLine } from '../../../../../src/shared/native-chat/tools/native-chat-diff'
import {
formatToolDuration,
mcpToolIdentity,
toolWebSearchResults,
type NativeChatWebSearchResult
} from '../../../src/shared/native-chat/tools/native-chat-tool-identity'
import { nativeChatToolIconName } from '../../../src/shared/native-chat/tools/native-chat-tool-icon'
} from '../../../../../src/shared/native-chat/tools/native-chat-tool-identity'
import { nativeChatToolIconName } from '../../../../../src/shared/native-chat/tools/native-chat-tool-icon'
import {
NATIVE_CHAT_TOOL_ROW_VERB_COPY,
nativeChatToolLineLabel
} from '../../../src/shared/native-chat/tools/native-chat-tool-line-label'
} from '../../../../../src/shared/native-chat/tools/native-chat-tool-line-label'
import {
isToolCallBlock,
type NativeChatToolCallBlock,
type NativeChatToolResultBlock
} from '../../../src/shared/native-chat-types'
import { MobileSyntaxSegments } from '../components/MobileSyntaxSegments'
import { INLINE_TEXT_SELECTION } from '../components/inline-text-selection'
import { openExternalLink } from '../platform/external-link'
import { colors } from '../theme/mobile-theme'
import { highlightMobileCode } from './mobile-file-syntax'
} from '../../../../../src/shared/native-chat-types'
import { MobileSyntaxSegments } from '../../../components/MobileSyntaxSegments'
import { INLINE_TEXT_SELECTION } from '../../../components/inline-text-selection'
import { openExternalLink } from '../../../platform/external-link'
import { colors } from '../../../theme/mobile-theme'
import { highlightMobileCode } from '../../mobile-file-syntax'
import { MobileNativeChatToolGlyph } from './MobileNativeChatToolIcon'
import { MobileNativeChatToolOutput } from './MobileNativeChatFullContent'
import { useMobileNativeChatOpenedDetail } from './mobile-native-chat-opened-detail'
import { useMobileNativeChatDisclosure } from './mobile-native-chat-disclosure-store'
import { MobileNativeChatToolOutput } from '../../MobileNativeChatFullContent'
import { useMobileNativeChatOpenedDetail } from '../../mobile-native-chat-opened-detail'
import { useMobileNativeChatDisclosure } from '../../mobile-native-chat-disclosure-store'
import { toolStyles as styles, toolType } from './mobile-native-chat-tool-styles'
const RESULT_LABEL = 'Result'
@@ -1,7 +1,7 @@
import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, expect, it, vi } from 'vitest'
import type { NativeChatBlock } from '../../../src/shared/native-chat-types'
import type { NativeChatBlock } from '../../../../../src/shared/native-chat-types'
vi.mock('react-native', () => ({
Animated: {
@@ -40,7 +40,9 @@ vi.mock('lucide-react-native', () => ({
Wrench: () => null
}))
vi.mock('../components/MobileSourceCopyButton', () => ({ MobileSourceCopyButton: 'CopyButton' }))
vi.mock('../../../components/MobileSourceCopyButton', () => ({
MobileSourceCopyButton: 'CopyButton'
}))
import { ToolRun } from './MobileNativeChatToolRun'
@@ -1,15 +1,15 @@
import { createElement, type ReactNode } from 'react'
import { act, create, type ReactTestInstance, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, describe, expect, it, vi } from 'vitest'
import type { AgentJournalToolCallItem } from '../../../src/shared/agent-session-journal-types'
import { MAX_TOOL_DETAIL_LENGTH } from '../../../src/shared/native-chat/tools/native-chat-tool-summary'
import { projectStructuredItemToNativeChat } from '../../../src/shared/structured-agent-session-projection'
import type { AgentJournalToolCallItem } from '../../../../../src/shared/agent-session-journal-types'
import { MAX_TOOL_DETAIL_LENGTH } from '../../../../../src/shared/native-chat/tools/native-chat-tool-summary'
import { projectStructuredItemToNativeChat } from '../../../../../src/shared/structured-agent-session-projection'
import type {
NativeChatBlock,
NativeChatMessage,
NativeChatToolCallBlock
} from '../../../src/shared/native-chat-types'
import { colors } from '../theme/mobile-theme'
} from '../../../../../src/shared/native-chat-types'
import { colors } from '../../../theme/mobile-theme'
const scrolls = vi.hoisted(() => ({ toEnd: vi.fn(), to: vi.fn() }))
@@ -67,16 +67,18 @@ vi.mock('lucide-react-native', () => ({
Wrench: 'Wrench'
}))
vi.mock('../components/MobileSourceCopyButton', () => ({ MobileSourceCopyButton: 'CopyButton' }))
vi.mock('../platform/external-link', () => ({ openExternalLink: vi.fn() }))
vi.mock('../components/inline-text-selection', () => ({ INLINE_TEXT_SELECTION: false }))
vi.mock('../../../components/MobileSourceCopyButton', () => ({
MobileSourceCopyButton: 'CopyButton'
}))
vi.mock('../../../platform/external-link', () => ({ openExternalLink: vi.fn() }))
vi.mock('../../../components/inline-text-selection', () => ({ INLINE_TEXT_SELECTION: false }))
import { openExternalLink } from '../platform/external-link'
import { openExternalLink } from '../../../platform/external-link'
import { ToolRun } from './MobileNativeChatToolRun'
import {
MobileNativeChatDisclosureContext,
useMobileNativeChatDisclosures
} from './mobile-native-chat-disclosure-store'
} from '../../mobile-native-chat-disclosure-store'
describe('ToolRun', () => {
let renderer: ReactTestRenderer | null = null
@@ -23,42 +23,41 @@ import {
describeLatestToolCall,
NATIVE_CHAT_TOOL_ACTIVITY_COPY,
selectActiveToolCall
} from '../../../src/shared/native-chat/tools/native-chat-tool-activity'
import { nativeChatToolRunIconName } from '../../../src/shared/native-chat/tools/native-chat-tool-icon'
import { nativeChatToolLineIdentity } from '../../../src/shared/native-chat/tools/native-chat-tool-line-identity'
import { pairNativeChatToolResults } from '../../../src/shared/native-chat/tools/native-chat-tool-pairing'
import { nativeChatToolRunOutcome } from '../../../src/shared/native-chat/tools/native-chat-tool-run-outcome'
} from '../../../../../src/shared/native-chat/tools/native-chat-tool-activity'
import { nativeChatToolRunIconName } from '../../../../../src/shared/native-chat/tools/native-chat-tool-icon'
import { nativeChatToolLineIdentity } from '../../../../../src/shared/native-chat/tools/native-chat-tool-line-identity'
import { pairNativeChatToolResults } from '../../../../../src/shared/native-chat/tools/native-chat-tool-pairing'
import { nativeChatToolRunOutcome } from '../../../../../src/shared/native-chat/tools/native-chat-tool-run-outcome'
import {
NATIVE_CHAT_TOOL_RUN_SENTENCE_ENGLISH,
nativeChatToolRunSentence
} from '../../../src/shared/native-chat/tools/native-chat-tool-run-sentence'
import { countToolCalls } from '../../../src/shared/native-chat/tools/native-chat-tool-summary'
import { buildEditCards } from '../../../src/shared/native-chat/tools/native-chat-edit-cards'
} from '../../../../../src/shared/native-chat/tools/native-chat-tool-run-sentence'
import { countToolCalls } from '../../../../../src/shared/native-chat/tools/native-chat-tool-summary'
import { buildEditCards } from '../../../../../src/shared/native-chat/tools/native-chat-edit-cards'
import {
isToolCallBlock,
type NativeChatBlock,
type NativeChatToolCallBlock
} from '../../../src/shared/native-chat-types'
import { buildNativeChatTaskListRows } from '../../../src/shared/native-chat/input/native-chat-task-list-history'
import { colors } from '../theme/mobile-theme'
} from '../../../../../src/shared/native-chat-types'
import { buildNativeChatTaskListRows } from '../../../../../src/shared/native-chat/input/native-chat-task-list-history'
import { colors } from '../../../theme/mobile-theme'
import { MobileNativeChatToolGlyph } from './MobileNativeChatToolIcon'
import { MobileNativeChatToolLine } from './MobileNativeChatToolLine'
import { MobileNativeChatDiffCard } from './MobileNativeChatDiffCard'
import { MobileNativeChatTaskList } from './native-chat/input/MobileNativeChatTaskList'
import { MobileNativeChatOpenedDetailContext } from './mobile-native-chat-opened-detail'
import { MobileNativeChatDiffCard } from '../../MobileNativeChatDiffCard'
import { MobileNativeChatTaskList } from '../input/MobileNativeChatTaskList'
import { MobileNativeChatOpenedDetailContext } from '../../mobile-native-chat-opened-detail'
import {
MAX_DISCLOSURES,
MobileNativeChatDisclosureContext,
useMobileNativeChatDisclosure
} from './mobile-native-chat-disclosure-store'
} from '../../mobile-native-chat-disclosure-store'
import { toolStyles as styles, toolType } from './mobile-native-chat-tool-styles'
import { mobileNativeChatMemberId } from './mobile-native-chat-reading-place'
import { MobileNativeChatOwnedScrollView } from './MobileNativeChatOwnedScrollView'
import { mobileNativeChatMemberId } from '../../mobile-native-chat-reading-place'
import { MobileNativeChatOwnedScrollView } from '../../MobileNativeChatOwnedScrollView'
import type {
MobileNativeChatToolRunAsides,
MobileNativeChatToolRunProps
} from './mobile-native-chat-tool-run-props'
export type { MobileNativeChatToolRunAsides } from './mobile-native-chat-tool-run-props'
/** Desktop's 18rem: an opened run lists this much before it scrolls in place. */
const MEMBERS_MIN_HEIGHT = 288
@@ -1,7 +1,7 @@
import type {
NativeChatBlock,
NativeChatToolCallBlock
} from '../../../src/shared/native-chat-types'
} from '../../../../../src/shared/native-chat-types'
export type MobileNativeChatToolRunAsides = {
before: ReadonlyMap<NativeChatBlock, readonly React.JSX.Element[]>
@@ -1,6 +1,6 @@
import { Platform, StyleSheet } from 'react-native'
import { colors, radii, spacing, typography } from '../theme/mobile-theme'
import { MONO_SIZE, scaledType } from './mobile-native-chat-message-styles'
import { colors, radii, spacing, typography } from '../../../theme/mobile-theme'
import { MONO_SIZE, scaledType } from '../../mobile-native-chat-message-styles'
export function toolType(fontScale: number) {
return {
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
import { summarizeToolInput } from '../../../src/shared/native-chat/tools/native-chat-tool-summary'
import { summarizeToolInput } from '../../../../../src/shared/native-chat/tools/native-chat-tool-summary'
describe('summarizeToolInput', () => {
it('does not traverse an unbounded tool-input object for a short preview', () => {
@@ -1,15 +1,15 @@
import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { pairToolBlocks } from '../../../src/shared/native-chat/tools/native-chat-tool-pairs'
import { nativeChatTurnMembership } from '../../../src/shared/native-chat-turn-membership'
import type { NativeChatMessage } from '../../../src/shared/native-chat-types'
import type { RpcClient } from '../transport/rpc-client'
import { foldMobileNativeChatMessages } from './mobile-native-chat-render-data'
import { pairToolBlocks } from '../../../../../src/shared/native-chat/tools/native-chat-tool-pairs'
import { nativeChatTurnMembership } from '../../../../../src/shared/native-chat-turn-membership'
import type { NativeChatMessage } from '../../../../../src/shared/native-chat-types'
import type { RpcClient } from '../../../transport/rpc-client'
import { foldMobileNativeChatMessages } from '../../mobile-native-chat-render-data'
import {
useMobileNativeChatSession,
type MobileNativeChatSession
} from './use-mobile-native-chat-session'
} from '../../use-mobile-native-chat-session'
function message(
id: string,