refactor(mobile): group native chat options and queued editing (#34074)

* refactor(mobile): group native chat options and queued editing

* refactor(mobile): use a concrete type import in the recording adapter
This commit is contained in:
Neil
2026-10-26 15:53:50 -07:00
committed by GitHub
parent 067c614764
commit 01fea97cde
37 changed files with 117 additions and 101 deletions
+9 -3
View File
@@ -16656,7 +16656,9 @@
"id": "native-chat-session-option-pick-written",
"operation": "nativeChat.session-option-pick",
"family": "nativeChat.session-option-pick",
"sites": ["mobile/src/session/mobile-native-chat-session-option-persistence.ts"],
"sites": [
"mobile/src/session/native-chat/input/mobile-native-chat-session-option-persistence.ts"
],
"schedules": [],
"steps": [
{
@@ -16692,7 +16694,9 @@
"id": "native-chat-session-option-pick-refused",
"operation": "nativeChat.session-option-pick",
"family": "nativeChat.session-option-pick",
"sites": ["mobile/src/session/mobile-native-chat-session-option-persistence.ts"],
"sites": [
"mobile/src/session/native-chat/input/mobile-native-chat-session-option-persistence.ts"
],
"schedules": [],
"steps": [
{
@@ -16729,7 +16733,9 @@
"id": "native-chat-session-option-pick-empty",
"operation": "nativeChat.session-option-pick",
"family": "nativeChat.session-option-pick",
"sites": ["mobile/src/session/mobile-native-chat-session-option-persistence.ts"],
"sites": [
"mobile/src/session/native-chat/input/mobile-native-chat-session-option-persistence.ts"
],
"schedules": [],
"steps": [
{
@@ -14,7 +14,9 @@ vi.mock('react-native', () => ({
vi.mock('./MobileNativeChatView', () => ({ MobileNativeChatView: 'ChatView' }))
vi.mock('../platform/use-reduced-motion', () => ({ useReducedMotionEnabled: () => null }))
vi.mock('./MobileNativeChatQueuedMessages', () => ({ MobileNativeChatQueuedMessages: 'Queued' }))
vi.mock('./native-chat/input/MobileNativeChatQueuedMessages', () => ({
MobileNativeChatQueuedMessages: 'Queued'
}))
vi.mock('./MobileNativeChatBackgroundTasks', () => ({
MobileNativeChatBackgroundTasks: 'BackgroundTasks'
}))
@@ -64,7 +64,7 @@ vi.mock('./MobileNativeChatMessage', () => ({ MobileNativeChatMessage: 'ChatMess
vi.mock('./MobileNativeChatLiveLine', () => ({ MobileNativeChatLiveLine: 'LiveStatus' }))
vi.mock('./MobileNativeChatAsk', () => ({ MobileNativeChatAsk: 'ChatAsk' }))
vi.mock('./MobileNativeChatQuestion', () => ({ MobileNativeChatQuestion: 'ChatQuestion' }))
vi.mock('./MobileNativeChatSessionOptionPickers', () => ({
vi.mock('./native-chat/input/MobileNativeChatSessionOptionPickers', () => ({
MobileNativeChatSessionOptionPickers: 'SessionOptions'
}))
vi.mock('./native-chat/composer/MobileNativeChatComposerMenu', () => ({
@@ -65,7 +65,8 @@ export function gestureHandlerStub() {
export async function composerStub() {
const React = await import('react')
const { MobileNativeChatStopButton } = await import('./MobileNativeChatStopButton')
const { MobileNativeChatStopButton } =
await import('./native-chat/input/MobileNativeChatStopButton')
return {
MobileNativeChatComposer: (props: {
onSend: (text: string) => Promise<boolean>
@@ -166,7 +166,9 @@ vi.mock('./MobileNativeChatAsk', () => ({ MobileNativeChatAsk: 'ChatAsk' }))
vi.mock('./MobileNativeChatPermission', () => ({ MobileNativeChatPermission: 'ChatPermission' }))
vi.mock('./MobileNativeChatQuestion', () => ({ MobileNativeChatQuestion: 'ChatQuestion' }))
vi.mock('../platform/use-reduced-motion', () => ({ useReducedMotionEnabled: () => true }))
vi.mock('./MobileNativeChatQueuedMessages', () => ({ MobileNativeChatQueuedMessages: 'Queued' }))
vi.mock('./native-chat/input/MobileNativeChatQueuedMessages', () => ({
MobileNativeChatQueuedMessages: 'Queued'
}))
vi.mock('./MobileNativeChatBackgroundTasks', () => ({
MobileNativeChatBackgroundTasks: 'BackgroundTasks'
}))
+1 -1
View File
@@ -52,7 +52,7 @@ import {
} from './native-chat/composer/use-mobile-native-chat-composer-tray'
import type { MobileChatPermission } from './mobile-native-chat-permission'
import type { MobileChatQuestion } from './mobile-native-chat-question'
import type { MobileNativeChatSessionOptionPickersProps } from './MobileNativeChatSessionOptionPickers'
import type { MobileNativeChatSessionOptionPickersProps } from './native-chat/input/MobileNativeChatSessionOptionPickers'
import { MobileNativeChatScrollRootsBoundary } from './MobileNativeChatScrollRootsBoundary'
import { MobileNativeChatRowList } from './MobileNativeChatRowList'
import { useMobileNativeChatRowRenderer } from './use-mobile-native-chat-row-renderer'
@@ -71,7 +71,8 @@ vi.mock('../components/ActionSheetModal', () => ({ ActionSheetModal: 'ActionShee
vi.mock('./native-chat/composer/MobileNativeChatComposer', async () => {
const React = await import('react')
const { MobileNativeChatStopButton } = await import('./MobileNativeChatStopButton')
const { MobileNativeChatStopButton } =
await import('./native-chat/input/MobileNativeChatStopButton')
return {
MobileNativeChatComposer: (props: {
onSend: (text: string) => Promise<boolean>
+1 -1
View File
@@ -1,7 +1,7 @@
import { useState } from 'react'
import { Pressable, StyleSheet, Text, View } from 'react-native'
import { colors, typography } from '../theme/mobile-theme'
import { queuedMessageStyles } from './mobile-native-chat-queued-message-styles'
import { queuedMessageStyles } from './native-chat/input/mobile-native-chat-queued-message-styles'
// Expand clipped queued text before Steer/Delete; use the queue’s capped scroller rather than nesting another scroll box.
export function MobileQueuedCardText({
@@ -11,9 +11,9 @@ import {
import { colors } from '../theme/mobile-theme'
import type { MobileQueuedMessageCard } from './mobile-structured-queued-message-cards'
import type { MobileQueuedMessageInlineEditor } from './use-mobile-structured-queued-edit'
import { MobileNativeChatQueuedMessageEditor } from './MobileNativeChatQueuedMessageEditor'
import { MobileNativeChatQueuedMessageEditor } from './native-chat/input/MobileNativeChatQueuedMessageEditor'
import { MobileQueuedCardText } from './MobileQueuedCardText'
import { queuedMessageStyles as styles } from './mobile-native-chat-queued-message-styles'
import { queuedMessageStyles as styles } from './native-chat/input/mobile-native-chat-queued-message-styles'
type QueuedMessageCardRowProps = {
card: MobileQueuedMessageCard
@@ -72,7 +72,7 @@ vi.mock('../MobileNativeChatVisual', () => ({ useMobileNativeChatVisualRenderer:
vi.mock('../../platform/use-reduced-motion', () => ({ useReducedMotionEnabled: () => null }))
vi.mock('../MobileNativeChatLiveLine', () => ({ MobileNativeChatLiveLine: 'LiveStatus' }))
vi.mock('../MobileNativeChatAsk', () => ({ MobileNativeChatAsk: 'ChatAsk' }))
vi.mock('../MobileNativeChatSessionOptionPickers', () => ({
vi.mock('../native-chat/input/MobileNativeChatSessionOptionPickers', () => ({
MobileNativeChatSessionOptionPickers: 'SessionOptions'
}))
vi.mock('../native-chat/composer/MobileNativeChatComposerMenu', () => ({
@@ -131,7 +131,7 @@ vi.mock('../native-chat/composer/use-mobile-native-chat-drafts', () => ({
holdUnconfirmedSend: vi.fn()
})
}))
vi.mock('../use-mobile-native-chat-session-option-controller', () => ({
vi.mock('../native-chat/input/use-mobile-native-chat-session-option-controller', () => ({
useMobileNativeChatSessionOptionController: () => ({
nativeChatSessionOptions: undefined,
recordCommand: vi.fn()
@@ -20,7 +20,7 @@ import type { MobileStructuredQueuedMessageControls } from './use-mobile-structu
import type { MobileStructuredBackgroundTasks } from './use-mobile-structured-background-tasks'
import type { MobileNativeChatPendingMessage } from './native-chat/mobile-native-chat-pending-echo'
import type { useMobileNativeChatSession } from './use-mobile-native-chat-session'
import type { MobileNativeChatSessionOptionPickersProps } from './MobileNativeChatSessionOptionPickers'
import type { MobileNativeChatSessionOptionPickersProps } from './native-chat/input/MobileNativeChatSessionOptionPickers'
import type { MobileNativeChatVisualSource } from './mobile-native-chat-visual-read'
import type { useMobileStructuredSessionCommands } from './use-mobile-structured-session-commands'
@@ -67,7 +67,9 @@ vi.mock('./MobileNativeChatLiveLine', () => ({ MobileNativeChatLiveLine: 'LiveSt
vi.mock('./native-chat/composer/MobileNativeChatComposer', () => ({
MobileNativeChatComposer: 'Composer'
}))
vi.mock('./MobileNativeChatQueuedMessages', () => ({ MobileNativeChatQueuedMessages: 'Queued' }))
vi.mock('./native-chat/input/MobileNativeChatQueuedMessages', () => ({
MobileNativeChatQueuedMessages: 'Queued'
}))
vi.mock('./MobileNativeChatVisual', () => ({ useMobileNativeChatVisualRenderer: () => null }))
vi.mock('../components/ActionSheetModal', () => ({ ActionSheetModal: 'ActionSheetModal' }))
vi.mock('./MobileNativeChatAsk', () => ({ MobileNativeChatAsk: 'ChatAsk' }))
@@ -13,13 +13,13 @@ import {
MobileNativeChatSessionOptionPickers,
type MobileNativeChatPickerPresentation,
type MobileNativeChatSessionOptionPickersProps
} from '../../MobileNativeChatSessionOptionPickers'
} from '../input/MobileNativeChatSessionOptionPickers'
import type { PendingNativeChatImage } from './mobile-native-chat-image-attachment'
import type { MobileComposerStructuredCatalog } from './mobile-native-chat-composer-menu'
import { useMobileNativeChatComposerMenu } from './use-mobile-native-chat-composer-menu'
import { keepHeldPressThroughLongPress } from '../../held-press-long-press'
import { mobileNativeChatComposerShowsStop } from './mobile-native-chat-composer-layout'
import { MobileNativeChatStopButton } from '../../MobileNativeChatStopButton'
import { MobileNativeChatStopButton } from '../input/MobileNativeChatStopButton'
import { mobileNativeChatComposerStyles as styles } from './mobile-native-chat-composer-styles'
const NO_FILE_PATHS: string[] = []
@@ -4,9 +4,9 @@ import { MobileNativeChatBackgroundTasks } from '../../MobileNativeChatBackgroun
import {
MobileNativeChatQueuedMessages,
type MobileNativeChatQueuedMessagesProps
} from '../../MobileNativeChatQueuedMessages'
} from '../input/MobileNativeChatQueuedMessages'
import type { MobileStructuredBackgroundTasks } from '../../use-mobile-structured-background-tasks'
import { useMobileNativeChatQueuedEditFocus } from '../../use-mobile-native-chat-queued-edit-focus'
import { useMobileNativeChatQueuedEditFocus } from '../input/use-mobile-native-chat-queued-edit-focus'
export type MobileNativeChatComposerTray = {
content?: ReactNode
@@ -10,10 +10,10 @@ import {
type ViewStyle
} from 'react-native'
import { Check, X } from 'lucide-react-native'
import { colors, radii, spacing, typography } from '../theme/mobile-theme'
import { mobileNativeChatInputStyles } from './native-chat/composer/mobile-native-chat-input-styles'
import type { MobileQueuedMessageInlineEditor } from './use-mobile-structured-queued-edit'
import { useTextInputContentHeight } from '../platform/text-input-content-height'
import { colors, radii, spacing, typography } from '../../../theme/mobile-theme'
import { mobileNativeChatInputStyles } from '../composer/mobile-native-chat-input-styles'
import type { MobileQueuedMessageInlineEditor } from '../../use-mobile-structured-queued-edit'
import { useTextInputContentHeight } from '../../../platform/text-input-content-height'
const BUTTON_SIZE = 28
const ICON_SIZE = 16
@@ -1,9 +1,9 @@
import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, describe, expect, it, vi } from 'vitest'
import type { ActionSheetAction } from '../components/ActionSheetModal'
import type { ActionSheetAction } from '../../../components/ActionSheetModal'
import { MobileNativeChatQueuedMessages } from './MobileNativeChatQueuedMessages'
import type { MobileQueuedMessageCard } from './mobile-structured-queued-message-cards'
import type { MobileQueuedMessageCard } from '../../mobile-structured-queued-message-cards'
let fontScale = 1
vi.mock('react-native', () => ({
@@ -33,7 +33,7 @@ vi.mock('lucide-react-native', () => ({
X: 'X'
}))
vi.mock('../components/ActionSheetModal', () => ({ ActionSheetModal: 'ActionSheetModal' }))
vi.mock('../../../components/ActionSheetModal', () => ({ ActionSheetModal: 'ActionSheetModal' }))
function card(
overrides: Partial<MobileQueuedMessageCard> & { messageId: string }
@@ -1,15 +1,15 @@
import { useRef, useState } from 'react'
import { Pressable, Text, View } from 'react-native'
import { ChevronDown, ChevronRight, Pencil, Play, Trash2 } from 'lucide-react-native'
import { ActionSheetModal } from '../components/ActionSheetModal'
import { colors } from '../theme/mobile-theme'
import { useLargeSystemText } from '../theme/use-large-system-text'
import type { MobileQueuedMessageCard } from './mobile-structured-queued-message-cards'
import type { MobileQueuePause } from './mobile-structured-queued-message-feed'
import type { MobileQueuedMessageEdit } from './use-mobile-structured-queued-message-controls'
import type { MobileQueuedMessageInlineEditor } from './use-mobile-structured-queued-edit'
import { MobileQueuedMessageCardRow } from './MobileQueuedMessageCardRow'
import { MobileQueuedMessageScrollList } from './MobileQueuedMessageScrollList'
import { ActionSheetModal } from '../../../components/ActionSheetModal'
import { colors } from '../../../theme/mobile-theme'
import { useLargeSystemText } from '../../../theme/use-large-system-text'
import type { MobileQueuedMessageCard } from '../../mobile-structured-queued-message-cards'
import type { MobileQueuePause } from '../../mobile-structured-queued-message-feed'
import type { MobileQueuedMessageEdit } from '../../use-mobile-structured-queued-message-controls'
import type { MobileQueuedMessageInlineEditor } from '../../use-mobile-structured-queued-edit'
import { MobileQueuedMessageCardRow } from '../../MobileQueuedMessageCardRow'
import { MobileQueuedMessageScrollList } from '../../MobileQueuedMessageScrollList'
import { queuedMessageStyles as styles } from './mobile-native-chat-queued-message-styles'
// Use NUL-prefixed header keys because message ids cannot contain NUL.
@@ -2,19 +2,22 @@ import { createElement, useState, type ReactNode } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { AccessibilityInfo, Platform } from 'react-native'
import { colors } from '../theme/mobile-theme'
import { structuredAgentSessionPermissionDescriptor } from '../../../src/shared/structured-agent-session-permission-option'
import { createStructuredAgentSessionOptionState } from '../../../src/shared/structured-agent-session-options'
import { colors } from '../../../theme/mobile-theme'
import { structuredAgentSessionPermissionDescriptor } from '../../../../../src/shared/structured-agent-session-permission-option'
import { createStructuredAgentSessionOptionState } from '../../../../../src/shared/structured-agent-session-options'
import type {
SessionOptionDescriptor,
SessionOptionSelectChoice
} from '../../../src/shared/native-chat-session-options'
} from '../../../../../src/shared/native-chat-session-options'
import {
MobileNativeChatSessionOptionPickers,
type MobileNativeChatPickerPresentation
} from './MobileNativeChatSessionOptionPickers'
import type { MobileNativeChatSessionOptionsController } from './use-mobile-native-chat-session-options'
import { findAllByHostType, findByHostType } from '../test-support/react-test-renderer-host-nodes'
import {
findAllByHostType,
findByHostType
} from '../../../test-support/react-test-renderer-host-nodes'
vi.mock('react-native', () => ({
AccessibilityInfo: { announceForAccessibilityWithOptions: vi.fn() },
@@ -39,7 +42,7 @@ vi.mock('lucide-react-native', () => ({
ShieldCheck: 'ShieldCheck',
X: 'X'
}))
vi.mock('../components/BottomDrawer', async () => {
vi.mock('../../../components/BottomDrawer', async () => {
const React = await import('react')
return {
BottomDrawer: ({ visible, children }: { visible: boolean; children?: ReactNode }) =>
@@ -19,14 +19,14 @@ import {
X,
type LucideIcon
} from 'lucide-react-native'
import { BottomDrawer } from '../components/BottomDrawer'
import { colors, radii, spacing, typography } from '../theme/mobile-theme'
import { BottomDrawer } from '../../../components/BottomDrawer'
import { colors, radii, spacing, typography } from '../../../theme/mobile-theme'
import {
isReadOnlySessionOptionValue,
sessionOptionDispatchUnconfirmed,
type SessionOptionDescriptor,
type SessionOptionValue
} from '../../../src/shared/native-chat-session-options'
} from '../../../../../src/shared/native-chat-session-options'
import {
mobileModelPillLabel,
mobileOptionsPillLabel,
@@ -43,12 +43,12 @@ import {
SessionOptionSegments,
showsSessionOptionAsSegments
} from './MobileNativeChatSessionOptionSegments'
import { sortNativeChatSessionOptions } from '../../../src/shared/native-chat-session-option-snapshot'
import { sortNativeChatSessionOptions } from '../../../../../src/shared/native-chat-session-option-snapshot'
import {
AGENT_CHAT_PERMISSION_MODE_ICON_NAMES,
AGENT_CHAT_PERMISSION_MODE_OPTION_ID,
isAgentChatPermissionMode
} from '../../../src/shared/agent-chat-permission-mode'
} from '../../../../../src/shared/agent-chat-permission-mode'
import type { MobileNativeChatSessionOptionsController } from './use-mobile-native-chat-session-options'
export type MobileNativeChatPickerPresentation = { page: string | null; refocus: boolean }
@@ -1,9 +1,12 @@
import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { describe, expect, it, vi } from 'vitest'
import type { SessionOptionDescriptor } from '../../../src/shared/native-chat-session-options'
import type { SessionOptionDescriptor } from '../../../../../src/shared/native-chat-session-options'
import { DescriptorRows } from './MobileNativeChatSessionOptionRows'
import { findAllByHostType, findByHostType } from '../test-support/react-test-renderer-host-nodes'
import {
findAllByHostType,
findByHostType
} from '../../../test-support/react-test-renderer-host-nodes'
vi.mock('react-native', () => ({
Pressable: 'Pressable',
@@ -1,12 +1,12 @@
import { Pressable, StyleSheet, Switch, Text, View } from 'react-native'
import { Check, ChevronRight, ShieldAlert, type LucideIcon } from 'lucide-react-native'
import { colors, radii, spacing, typography } from '../theme/mobile-theme'
import { colors, radii, spacing, typography } from '../../../theme/mobile-theme'
import {
sessionOptionValueMarker,
type SessionOptionDescriptor,
type SessionOptionValueMarker,
type SessionOptionValue
} from '../../../src/shared/native-chat-session-options'
} from '../../../../../src/shared/native-chat-session-options'
export function SessionOptionCaption({ children }: { children: string }): React.JSX.Element {
return <Text style={styles.caption}>{children}</Text>
@@ -1,11 +1,11 @@
import { StyleSheet, Text, View } from 'react-native'
import { MobileSegmentedControl } from '../components/MobileSegmentedControl'
import { colors, spacing, typography } from '../theme/mobile-theme'
import { MobileSegmentedControl } from '../../../components/MobileSegmentedControl'
import { colors, spacing, typography } from '../../../theme/mobile-theme'
import {
sessionOptionDispatchUnconfirmed,
type SessionOptionDescriptor,
type SessionOptionValue
} from '../../../src/shared/native-chat-session-options'
} from '../../../../../src/shared/native-chat-session-options'
import { SessionOptionCaption } from './MobileNativeChatSessionOptionRows'
// Five fit across a phone's sheet; more read better as a list on their own page.
@@ -1,8 +1,8 @@
import { ActivityIndicator, Pressable } from 'react-native'
import { Square } from 'lucide-react-native'
import { NATIVE_CHAT_TURN_STATUS_COPY } from '../../../src/shared/native-chat-turn-status'
import { colors } from '../theme/mobile-theme'
import { mobileNativeChatComposerStyles as styles } from './native-chat/composer/mobile-native-chat-composer-styles'
import { NATIVE_CHAT_TURN_STATUS_COPY } from '../../../../../src/shared/native-chat-turn-status'
import { colors } from '../../../theme/mobile-theme'
import { mobileNativeChatComposerStyles as styles } from '../composer/mobile-native-chat-composer-styles'
// held tracks this phone’s in-flight Stop request, not the host’s stopping status.
export function MobileNativeChatStopButton({
@@ -1,6 +1,6 @@
import { StyleSheet } from 'react-native'
import { colors, radii, spacing, typography } from '../theme/mobile-theme'
import { COMPOSER_INSET_TOP } from './native-chat/composer/mobile-native-chat-composer-styles'
import { colors, radii, spacing, typography } from '../../../theme/mobile-theme'
import { COMPOSER_INSET_TOP } from '../composer/mobile-native-chat-composer-styles'
// Keep 44pt targets inside the parent row because Android drops outside touches.
const MIN_TOUCH_TARGET = 44
@@ -3,7 +3,7 @@ import {
type SessionOptionDescriptor,
type SessionOptionDisabledReason,
type SessionOptionSelectChoice
} from '../../../src/shared/native-chat-session-options'
} from '../../../../../src/shared/native-chat-session-options'
export function mobileSessionOptionDisabledReason(
reason: SessionOptionDisabledReason | undefined
@@ -2,9 +2,9 @@ import { describe, expect, it, vi } from 'vitest'
import {
applyNativeChatSessionOptionSettingsMutation,
resolveStructuredLaunchSeedOptions
} from '../../../src/shared/native-chat-session-option-defaults'
import type { PersistedNativeChatSessionOptions } from '../../../src/shared/native-chat-session-options'
import type { RpcClient } from '../transport/rpc-client'
} from '../../../../../src/shared/native-chat-session-option-defaults'
import type { PersistedNativeChatSessionOptions } from '../../../../../src/shared/native-chat-session-options'
import type { RpcClient } from '../../../transport/rpc-client'
import { persistMobileStructuredOptionPicks } from './mobile-native-chat-session-option-persistence'
function hostClient(initial?: PersistedNativeChatSessionOptions) {
@@ -1,7 +1,7 @@
import type { AgentType } from '../../../src/shared/agent-status-types'
import type { StructuredSessionOptionPick } from '../../../src/shared/structured-agent-session-options'
import type { RpcClient } from '../transport/rpc-client'
import { nativeChatSessionOptionsWrite } from './mobile-session-launch-operations'
import type { AgentType } from '../../../../../src/shared/agent-status-types'
import type { StructuredSessionOptionPick } from '../../../../../src/shared/structured-agent-session-options'
import type { RpcClient } from '../../../transport/rpc-client'
import { nativeChatSessionOptionsWrite } from '../../mobile-session-launch-operations'
// Persist picks on the host that seeds future sessions; best-effort failure only loses that next-session default.
export function persistMobileStructuredOptionPicks(args: {
@@ -2,7 +2,7 @@ import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useMobileNativeChatQueuedEditFocus } from './use-mobile-native-chat-queued-edit-focus'
import type { MobileQueuedMessageEdit } from './use-mobile-structured-queued-message-controls'
import type { MobileQueuedMessageEdit } from '../../use-mobile-structured-queued-message-controls'
type Focus = ReturnType<typeof useMobileNativeChatQueuedEditFocus>
@@ -1,6 +1,6 @@
import { useMemo, useRef, type RefObject } from 'react'
import type { TextInput } from 'react-native'
import type { MobileQueuedMessageEdit } from './use-mobile-structured-queued-message-controls'
import type { MobileQueuedMessageEdit } from '../../use-mobile-structured-queued-message-controls'
// Focus after a queued Edit actually copies text; empty copies preserve current focus.
export function useMobileNativeChatQueuedEditFocus(onEdit: MobileQueuedMessageEdit | undefined): {
@@ -1,14 +1,14 @@
import type { RpcClient } from '../transport/rpc-client'
import { useMobileOmpModelDiscovery } from './use-mobile-omp-model-discovery'
import type { AgentSessionConversationCommand } from '../../../src/shared/agent-session/agent-session-conversation-command'
import type { RpcClient } from '../../../transport/rpc-client'
import { useMobileOmpModelDiscovery } from '../../use-mobile-omp-model-discovery'
import type { AgentSessionConversationCommand } from '../../../../../src/shared/agent-session/agent-session-conversation-command'
import { useCallback, useMemo } from 'react'
import type {
SessionOptionDescriptor,
SessionOptionValue,
SessionOptionsSurface
} from '../../../src/shared/native-chat-session-options'
import { mobileNativeChatScopeKey } from './native-chat/mobile-native-chat-scope-key'
import type { MobileNativeChatSendOutcome } from './native-chat/mobile-native-chat-send'
} from '../../../../../src/shared/native-chat-session-options'
import { mobileNativeChatScopeKey } from '../mobile-native-chat-scope-key'
import type { MobileNativeChatSendOutcome } from '../mobile-native-chat-send'
import type { MobileNativeChatSessionOptionPickersProps } from './MobileNativeChatSessionOptionPickers'
import {
useMobileNativeChatSessionOptions,
@@ -1,12 +1,12 @@
import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { MobileNativeChatSendOutcome } from './native-chat/mobile-native-chat-send'
import type { MobileNativeChatSendOutcome } from '../mobile-native-chat-send'
import {
clearMobileSessionOptionRecordsForTests,
useMobileNativeChatSessionOptions,
type MobileNativeChatSessionOptionsController
} from './use-mobile-native-chat-session-options'
import { clearMobileSessionOptionRecordsForTests } from '../../mobile-session-option-records'
type HookArgs = Parameters<typeof useMobileNativeChatSessionOptions>[0]
@@ -1,27 +1,26 @@
import { appliedReportByScope, getScopedRecord } from './mobile-session-option-records'
export { clearMobileSessionOptionRecordsForTests } from './mobile-session-option-records'
import { mobileOmpSessionCatalog } from './mobile-omp-session-catalog'
import type { AgentSessionConversationCommand } from '../../../src/shared/agent-session/agent-session-conversation-command'
import { appliedReportByScope, getScopedRecord } from '../../mobile-session-option-records'
import { mobileOmpSessionCatalog } from '../../mobile-omp-session-catalog'
import type { AgentSessionConversationCommand } from '../../../../../src/shared/agent-session/agent-session-conversation-command'
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import {
getAgentSessionOptionCatalog,
type CatalogCommandDelivery,
type CatalogModel
} from '../../../src/shared/agent-session-option-catalog'
import { getAgentSessionOptionCatalog } from '../../../../../src/shared/agent-session-option-catalog'
import type {
CatalogCommandDelivery,
CatalogModel
} from '../../../../../src/shared/agent-session-option-catalog-types'
import type {
SessionOptionsSurface,
SessionOptionDescriptor,
SessionOptionValue
} from '../../../src/shared/native-chat-session-options'
import type { MobileNativeChatSendOutcome } from './native-chat/mobile-native-chat-send'
} from '../../../../../src/shared/native-chat-session-options'
import type { MobileNativeChatSendOutcome } from '../mobile-native-chat-send'
import {
buildNativeChatSessionOptionCommand,
recordNativeChatSessionOptionCommand
} from '../../../src/shared/native-chat-session-option-commands'
} from '../../../../../src/shared/native-chat-session-option-commands'
import {
buildNativeChatSessionOptionSnapshot,
withTrackedNativeChatModel
} from '../../../src/shared/native-chat-session-option-snapshot'
} from '../../../../../src/shared/native-chat-session-option-snapshot'
import {
applyNativeChatReportedSessionOptions,
clearNativeChatSessionModel,
@@ -29,7 +28,7 @@ import {
isFlipOnlyMidSession,
matchNativeChatCatalogModelId,
setTrackedSessionOption
} from '../../../src/shared/native-chat-session-option-state'
} from '../../../../../src/shared/native-chat-session-option-state'
export type MobileNativeChatSessionOptionsController = {
optionSurface?: SessionOptionsSurface
@@ -8,7 +8,7 @@ import { useMobileNativeChatDrafts } from './native-chat/composer/use-mobile-nat
import { useMobileNativeChatFileSearch } from './native-chat/composer/use-mobile-native-chat-file-search'
import { useMobileNativeChatMessageSend } from './use-mobile-native-chat-message-send'
import { mobileNativeChatStreamPreview } from './native-chat/mobile-native-chat-streaming-gate'
import { useMobileNativeChatSessionOptionController } from './use-mobile-native-chat-session-option-controller'
import { useMobileNativeChatSessionOptionController } from './native-chat/input/use-mobile-native-chat-session-option-controller'
import { useMobileNativeChatSessionLane } from './use-mobile-native-chat-session-lane'
import { useMobileStructuredNativeChatSendBridge } from './use-mobile-structured-native-chat-send-bridge'
import { useMobileNativeChatPrompts } from './use-mobile-native-chat-prompts'
@@ -2,10 +2,8 @@ import { createElement } from 'react'
import { act, create } from 'react-test-renderer'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useMobileOmpModelDiscovery } from './use-mobile-omp-model-discovery'
import {
useMobileNativeChatSessionOptions,
clearMobileSessionOptionRecordsForTests
} from './use-mobile-native-chat-session-options'
import { useMobileNativeChatSessionOptions } from './native-chat/input/use-mobile-native-chat-session-options'
import { clearMobileSessionOptionRecordsForTests } from './mobile-session-option-records'
import type { RpcResponse } from '../transport/types'
@@ -25,7 +25,7 @@ import { legacyHostPermissionDescriptor } from '../../../src/shared/structured-a
import type { RpcClient } from '../transport/rpc-client'
import type { StructuredAgentSessionHostSupport } from './mobile-structured-agent-session-host-support'
import type { StructuredAgentSessionMutate } from './mobile-structured-agent-session-rpc'
import { persistMobileStructuredOptionPicks } from './mobile-native-chat-session-option-persistence'
import { persistMobileStructuredOptionPicks } from './native-chat/input/mobile-native-chat-session-option-persistence'
import { useMobileHostModelCatalogUpgrade } from './use-mobile-host-model-catalog-upgrade'
import { mobileCreatedStructuredSession } from './mobile-created-structured-sessions'
import { encodeStructuredAgentSessionOptionValue } from '../../../src/shared/structured-agent-session-option-codec'
@@ -2,6 +2,7 @@ import type { MountAdapter } from '../recording-scenario'
import { mountFixture } from '../recorder-fixture-shape'
import type { operationModuleLoader } from '../operation-module-loader'
import type * as NativeChatSend from '../../../session/native-chat/mobile-native-chat-send'
import type * as NativeChatSessionOptionPersistence from '../../../session/native-chat/input/mobile-native-chat-session-option-persistence'
const TERMINAL = 'terminal-1'
const DEVICE_TOKEN = 'device-token-1'
@@ -61,10 +62,8 @@ export function nativeChatWriteMountAdapters(
}
},
'nativeChat.session-option-pick': ({ client }) => {
const persist = modules.load<
typeof import('../../../session/mobile-native-chat-session-option-persistence')
>(
'mobile/src/session/mobile-native-chat-session-option-persistence.ts'
const persist = modules.load<typeof NativeChatSessionOptionPersistence>(
'mobile/src/session/native-chat/input/mobile-native-chat-session-option-persistence.ts'
).persistMobileStructuredOptionPicks
let settled: unknown = 'unsent'
return {