mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
refactor: group mobile chat composer ownership (#33390)
* refactor: group mobile chat composer ownership * refactor: use explicit type imports in moved chat adapters
This commit is contained in:
@@ -2018,7 +2018,7 @@
|
||||
"oracle": "Inject adapter/RPC acknowledgement loss, caller replacement, logical-client close after response, auth recovery with a written request, missing host submissions, legacy pending rows, stale fences, expiry, mobile remount, and phone storage refusal. Assert at most one dispatch for repeated transmission of one operation. For a later phone Send, assert a fresh id and second delivery while the original host entry remains unknown; equal images use current uploaded paths and delivery fields follow current host capabilities.",
|
||||
"commands": [
|
||||
"ORCA_BACKGROUND_LAUNCH=1 pnpm test src/shared/agent-session-operation-ledger.test.ts src/shared/structured-agent-session-send-evidence.test.ts src/main/runtime/agent-session/ownership/agent-session-operation-admission.test.ts src/main/native-chat/agent-session-wire/structured-agent-session-send-idempotency.test.ts src/main/native-chat/agent-session-wire/structured-agent-session-send.test.ts src/main/runtime/orchestration/structured-mailbox-pointer-delivery.test.ts src/main/runtime/orchestration/structured-mailbox-pointer-host.test.ts src/main/runtime/orchestration/structured-pointer-operation-id.test.ts src/renderer/src/components/native-chat/structured-agent-session-message-sender.test.ts src/renderer/src/components/native-chat/use-structured-agent-session.test.tsx src/renderer/src/lib/launch-structured-agent-session.test.ts",
|
||||
"ORCA_BACKGROUND_LAUNCH=1 pnpm --dir mobile test ../mobile/src/session/mobile-structured-send-new-action.test.ts ../mobile/src/session/use-mobile-structured-agent-session-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-queued.test.tsx ../mobile/src/session/mobile-structured-send-delivery.test.ts ../mobile/src/session/use-mobile-structured-agent-session-background-tasks.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-newer-approval-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-read-failure.test.tsx ../mobile/src/session/use-mobile-structured-agent-session.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-prompt-cancel.test.tsx ../mobile/src/session/mobile-native-chat-image-attachment.test.ts ../mobile/src/session/use-mobile-native-chat-image-attachments.test.ts ../mobile/src/session/use-mobile-structured-native-chat-send-bridge.test.ts ../mobile/src/mobile-web-shell/page-storage-keys.test.ts ../mobile/src/mobile-web-shell/bridge/page-async-storage.test.ts ../mobile/src/mobile-web-shell/use-page-host-snapshot.test.tsx ../mobile/src/mobile-web-shell/bridge-host-init.test.ts ../mobile/src/transport/mobile-relay-rpc-session.test.ts ../mobile/src/transport/rpc-client-delivery-ambiguity.test.ts ../mobile/src/transport/stable-logical-rpc-client.test.ts --maxWorkers=2"
|
||||
"ORCA_BACKGROUND_LAUNCH=1 pnpm --dir mobile test ../mobile/src/session/mobile-structured-send-new-action.test.ts ../mobile/src/session/use-mobile-structured-agent-session-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-queued.test.tsx ../mobile/src/session/mobile-structured-send-delivery.test.ts ../mobile/src/session/use-mobile-structured-agent-session-background-tasks.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-newer-approval-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-read-failure.test.tsx ../mobile/src/session/use-mobile-structured-agent-session.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-prompt-cancel.test.tsx ../mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.test.ts ../mobile/src/session/native-chat/composer/use-mobile-native-chat-image-attachments.test.ts ../mobile/src/session/use-mobile-structured-native-chat-send-bridge.test.ts ../mobile/src/mobile-web-shell/page-storage-keys.test.ts ../mobile/src/mobile-web-shell/bridge/page-async-storage.test.ts ../mobile/src/mobile-web-shell/use-page-host-snapshot.test.tsx ../mobile/src/mobile-web-shell/bridge-host-init.test.ts ../mobile/src/transport/mobile-relay-rpc-session.test.ts ../mobile/src/transport/rpc-client-delivery-ambiguity.test.ts ../mobile/src/transport/stable-logical-rpc-client.test.ts --maxWorkers=2"
|
||||
],
|
||||
"testFiles": [
|
||||
"src/shared/agent-session-operation-ledger.test.ts",
|
||||
@@ -2032,8 +2032,8 @@
|
||||
"src/renderer/src/components/native-chat/structured-agent-session-message-sender.test.ts",
|
||||
"src/renderer/src/components/native-chat/use-structured-agent-session.test.tsx",
|
||||
"src/renderer/src/lib/launch-structured-agent-session.test.ts",
|
||||
"mobile/src/session/mobile-native-chat-image-attachment.test.ts",
|
||||
"mobile/src/session/use-mobile-native-chat-image-attachments.test.ts",
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.test.ts",
|
||||
"mobile/src/session/native-chat/composer/use-mobile-native-chat-image-attachments.test.ts",
|
||||
"mobile/src/session/mobile-structured-send-new-action.test.ts",
|
||||
"mobile/src/session/mobile-structured-send-delivery.test.ts",
|
||||
"mobile/src/session/use-mobile-structured-agent-session-send.test.tsx",
|
||||
@@ -2118,7 +2118,8 @@
|
||||
"command": "ORCA_BACKGROUND_LAUNCH=1 pnpm --dir mobile test ../mobile/src/session/mobile-structured-send-new-action.test.ts ../mobile/src/session/use-mobile-structured-agent-session-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-queued.test.tsx ../mobile/src/session/mobile-structured-send-delivery.test.ts ../mobile/src/session/use-mobile-structured-agent-session-background-tasks.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-newer-approval-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-read-failure.test.tsx ../mobile/src/session/use-mobile-structured-agent-session.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-prompt-cancel.test.tsx ../mobile/src/session/mobile-native-chat-image-attachment.test.ts ../mobile/src/session/use-mobile-native-chat-image-attachments.test.ts ../mobile/src/session/use-mobile-structured-native-chat-send-bridge.test.ts ../mobile/src/mobile-web-shell/page-storage-keys.test.ts ../mobile/src/mobile-web-shell/bridge/page-async-storage.test.ts ../mobile/src/mobile-web-shell/use-page-host-snapshot.test.tsx ../mobile/src/mobile-web-shell/bridge-host-init.test.ts ../mobile/src/transport/mobile-relay-rpc-session.test.ts ../mobile/src/transport/rpc-client-delivery-ambiguity.test.ts ../mobile/src/transport/stable-logical-rpc-client.test.ts --maxWorkers=2",
|
||||
"result": "passed",
|
||||
"durationSeconds": 5.42,
|
||||
"summary": "Nineteen focused mobile files passed 241 tests for fresh Send identity, remount, attachment paths, storage refusal, mixed host capabilities, queued cards, and written-request ambiguity."
|
||||
"summary": "Nineteen focused mobile files passed 241 tests for fresh Send identity, remount, attachment paths, storage refusal, mixed host capabilities, queued cards, and written-request ambiguity.",
|
||||
"currentCommand": "ORCA_BACKGROUND_LAUNCH=1 pnpm --dir mobile test ../mobile/src/session/mobile-structured-send-new-action.test.ts ../mobile/src/session/use-mobile-structured-agent-session-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-queued.test.tsx ../mobile/src/session/mobile-structured-send-delivery.test.ts ../mobile/src/session/use-mobile-structured-agent-session-background-tasks.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-newer-approval-send.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-read-failure.test.tsx ../mobile/src/session/use-mobile-structured-agent-session.test.tsx ../mobile/src/session/use-mobile-structured-agent-session-prompt-cancel.test.tsx ../mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.test.ts ../mobile/src/session/native-chat/composer/use-mobile-native-chat-image-attachments.test.ts ../mobile/src/session/use-mobile-structured-native-chat-send-bridge.test.ts ../mobile/src/mobile-web-shell/page-storage-keys.test.ts ../mobile/src/mobile-web-shell/bridge/page-async-storage.test.ts ../mobile/src/mobile-web-shell/use-page-host-snapshot.test.tsx ../mobile/src/mobile-web-shell/bridge-host-init.test.ts ../mobile/src/transport/mobile-relay-rpc-session.test.ts ../mobile/src/transport/rpc-client-delivery-ambiguity.test.ts ../mobile/src/transport/stable-logical-rpc-client.test.ts --maxWorkers=2"
|
||||
},
|
||||
{
|
||||
"date": "2026-10-13",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"id": "b1",
|
||||
"operation": "workspace.file-inventory",
|
||||
"family": "legacy-inventory",
|
||||
"sites": ["mobile/src/session/use-mobile-native-chat-file-search.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/use-mobile-native-chat-file-search.ts"],
|
||||
"schedules": ["a-b-a", "stale-inflight-cleanup"],
|
||||
"steps": [
|
||||
{
|
||||
@@ -2508,7 +2508,7 @@
|
||||
"id": "inventory-lifecycle",
|
||||
"operation": "workspace.file-inventory",
|
||||
"family": "legacy-inventory",
|
||||
"sites": ["mobile/src/session/use-mobile-native-chat-file-search.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/use-mobile-native-chat-file-search.ts"],
|
||||
"schedules": ["reset", "unmount-remount", "blur-retained-route"],
|
||||
"steps": [
|
||||
{
|
||||
@@ -2572,7 +2572,7 @@
|
||||
"id": "inventory-repeat-query",
|
||||
"operation": "workspace.file-inventory",
|
||||
"family": "legacy-inventory",
|
||||
"sites": ["mobile/src/session/use-mobile-native-chat-file-search.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/use-mobile-native-chat-file-search.ts"],
|
||||
"schedules": ["normalized-repeat", "cache-cancels-debounce", "cache-stales-inflight"],
|
||||
"steps": [
|
||||
{
|
||||
@@ -16143,7 +16143,7 @@
|
||||
"id": "native-chat-image-paste-single",
|
||||
"operation": "nativeChat.image-paste",
|
||||
"family": "nativeChat.image-paste",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -16199,7 +16199,7 @@
|
||||
"id": "native-chat-image-paste-two-images",
|
||||
"operation": "nativeChat.image-paste",
|
||||
"family": "nativeChat.image-paste",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -16275,7 +16275,7 @@
|
||||
"id": "native-chat-image-paste-stops-on-rejection",
|
||||
"operation": "nativeChat.image-paste",
|
||||
"family": "nativeChat.image-paste",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -16331,7 +16331,7 @@
|
||||
"id": "native-chat-image-paste-trailing-image",
|
||||
"operation": "nativeChat.image-paste",
|
||||
"family": "nativeChat.image-paste",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18983,7 +18983,7 @@
|
||||
"id": "native-chat-image-upload-start-refused",
|
||||
"operation": "nativeChat.image-upload",
|
||||
"family": "nativeChat.image-upload",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-attachment.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19013,7 +19013,7 @@
|
||||
"id": "native-chat-image-upload-single",
|
||||
"operation": "nativeChat.image-upload",
|
||||
"family": "nativeChat.image-upload",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-attachment.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19066,7 +19066,7 @@
|
||||
"id": "native-chat-image-upload-two",
|
||||
"operation": "nativeChat.image-upload",
|
||||
"family": "nativeChat.image-upload",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-attachment.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19156,7 +19156,7 @@
|
||||
"id": "native-chat-image-upload-second-fails",
|
||||
"operation": "nativeChat.image-upload",
|
||||
"family": "nativeChat.image-upload",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-attachment.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19223,7 +19223,7 @@
|
||||
"id": "native-chat-image-upload-cancelled",
|
||||
"operation": "nativeChat.image-upload",
|
||||
"family": "nativeChat.image-upload",
|
||||
"sites": ["mobile/src/session/mobile-native-chat-image-attachment.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
|
||||
@@ -5,8 +5,8 @@ import { colors } from '../theme/mobile-theme'
|
||||
import { NATIVE_CHAT_COMPOSER_PLACEHOLDER } from '../../../src/shared/native-chat-turn-status'
|
||||
import { MobileNativeChatComposerMenu } from './MobileNativeChatComposerMenu'
|
||||
import { MobileNativeChatComposerField } from './MobileNativeChatComposerField'
|
||||
import { MobileNativeChatComposerAttachments } from './MobileNativeChatComposerAttachments'
|
||||
import type { PendingNativeChatFile } from './mobile-native-chat-file-attachment'
|
||||
import { MobileNativeChatComposerAttachments } from './native-chat/composer/MobileNativeChatComposerAttachments'
|
||||
import type { PendingNativeChatFile } from './native-chat/composer/mobile-native-chat-file-attachment'
|
||||
import { ActionSheetModal } from '../components/ActionSheetModal'
|
||||
import { mobileNativeChatAttachActions } from './mobile-native-chat-attach-actions'
|
||||
import {
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
type MobileNativeChatPickerPresentation,
|
||||
type MobileNativeChatSessionOptionPickersProps
|
||||
} from './MobileNativeChatSessionOptionPickers'
|
||||
import type { PendingNativeChatImage } from './mobile-native-chat-image-attachment'
|
||||
import type { PendingNativeChatImage } from './native-chat/composer/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'
|
||||
|
||||
@@ -3,7 +3,7 @@ import { StyleSheet, View } from 'react-native'
|
||||
import { MobileNativeChatView, type MobileNativeChatInputLockReason } from './MobileNativeChatView'
|
||||
import { foldMobileNativeChatMessages } from './mobile-native-chat-render-data'
|
||||
import { useMobileNativeChatFoldReuse } from './mobile-native-chat-fold-reuse'
|
||||
import type { MobileNativeChatImageAttachments } from './use-mobile-native-chat-image-attachments'
|
||||
import type { MobileNativeChatImageAttachments } from './native-chat/composer/use-mobile-native-chat-image-attachments'
|
||||
import type { MobileNativeChatController } from './use-mobile-native-chat-controller'
|
||||
import type { MobileNativeChatStructuredComposer } from './MobileNativeChatComposer'
|
||||
import { useMobileNativeChatStreamingBubble } from './use-mobile-native-chat-streaming-bubble'
|
||||
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
} from './use-mobile-native-chat-input-lease'
|
||||
import { MobileNativeChatLiveLine } from './MobileNativeChatLiveLine'
|
||||
import { MobileNativeChatFloatingControls } from './MobileNativeChatFloatingControls'
|
||||
import type { PendingNativeChatImage } from './mobile-native-chat-image-attachment'
|
||||
import type { PendingNativeChatImage } from './native-chat/composer/mobile-native-chat-image-attachment'
|
||||
import {
|
||||
MobileNativeChatComposer,
|
||||
type MobileNativeChatStructuredComposer
|
||||
|
||||
@@ -136,7 +136,7 @@ vi.mock('../use-mobile-native-chat-session-option-controller', () => ({
|
||||
recordCommand: vi.fn()
|
||||
})
|
||||
}))
|
||||
vi.mock('../use-mobile-native-chat-file-search', () => ({
|
||||
vi.mock('../native-chat/composer/use-mobile-native-chat-file-search', () => ({
|
||||
useMobileNativeChatFileSearch: () => ({ nativeChatFilePaths: [], loadNativeChatFiles: vi.fn() })
|
||||
}))
|
||||
vi.mock('../use-mobile-native-chat-composer-tray', () => ({
|
||||
|
||||
@@ -3,7 +3,7 @@ import { act, create } from 'react-test-renderer'
|
||||
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import { MobileNativeChatComposer } from './MobileNativeChatComposer'
|
||||
import { useMobileNativeChatFileSearch } from './use-mobile-native-chat-file-search'
|
||||
import { useMobileNativeChatFileSearch } from './native-chat/composer/use-mobile-native-chat-file-search'
|
||||
import { stubRpcClient } from '../transport/rpc-client-test-stub'
|
||||
|
||||
vi.mock('react-native', async () => {
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
normalizeImageTranscriptMessages,
|
||||
normalizeNativeChatUserText,
|
||||
normalizedNativeChatUserMessageText
|
||||
} from './mobile-native-chat-image-transcript-markers'
|
||||
export { normalizeNativeChatUserText as normalizeReconcileText } from './mobile-native-chat-image-transcript-markers'
|
||||
} from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
|
||||
/** An ack-lost ('unknown' outcome) send held until its transcript echo lands or
|
||||
* the deadline surfaces the uncertainty. */
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
// Single-sources the marker logic (pure functions over shared types):
|
||||
// Claude records an attached image as `[Image: source: /path]` (+ `[Image #N]`
|
||||
// on the caption turn), and both render and echo reconciliation must
|
||||
// agree with desktop on how those marker turns are interpreted.
|
||||
export {
|
||||
imageSourcePathFromText,
|
||||
hasImagePromptMarker,
|
||||
isImageSourceUserTurn,
|
||||
normalizeImageTranscriptMessages,
|
||||
normalizeNativeChatUserText,
|
||||
normalizedNativeChatUserMessageText,
|
||||
stripImagePromptMarker
|
||||
} from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { NativeChatMessage } from '../../../src/shared/native-chat-types'
|
||||
import { normalizeReconcileText } from './mobile-native-chat-draft-reconcile'
|
||||
import { normalizeNativeChatUserText as normalizeReconcileText } from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
import type { MobileNativeChatPendingMessage } from './mobile-native-chat-pending-echo'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { NativeChatMessage } from '../../../src/shared/native-chat-types'
|
||||
import {
|
||||
countUserTextOccurrences,
|
||||
normalizeReconcileText
|
||||
} from './mobile-native-chat-draft-reconcile'
|
||||
import { countUserTextOccurrences } from './mobile-native-chat-draft-reconcile'
|
||||
import { normalizeNativeChatUserText as normalizeReconcileText } from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
import {
|
||||
appendMobileNativeChatPending,
|
||||
type MobileNativeChatSendOrigin
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { normalizeReconcileText } from './mobile-native-chat-draft-reconcile'
|
||||
import { normalizeNativeChatUserText as normalizeReconcileText } from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
|
||||
export type MobileNativeChatPendingMessage = {
|
||||
id: string
|
||||
|
||||
@@ -2,9 +2,9 @@ import { nativeChatContinuationSendText } from '../../../src/shared/native-chat-
|
||||
import type { NativeChatMessage } from '../../../src/shared/native-chat-types'
|
||||
import {
|
||||
countImageSourceTurnsAfter,
|
||||
normalizeReconcileText,
|
||||
normalizedUserText
|
||||
} from './mobile-native-chat-draft-reconcile'
|
||||
import { normalizeNativeChatUserText as normalizeReconcileText } from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
import type { MobileNativeChatPendingMessage } from './mobile-native-chat-pending-echo'
|
||||
|
||||
const SPACE = ' '
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
type AgentType,
|
||||
type NativeChatMessage
|
||||
} from '../../../src/shared/native-chat-types'
|
||||
import { isImageSourceUserTurn } from './mobile-native-chat-image-transcript-markers'
|
||||
import { isImageSourceUserTurn } from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
import type { MobileNativeChatStatus } from './use-mobile-native-chat-session'
|
||||
|
||||
/** The centered empty-state copy for a chat with no messages, mirroring the
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { pasteMobileNativeChatImagePaths } from './mobile-native-chat-image-send'
|
||||
import { pasteMobileNativeChatImagePaths } from './native-chat/composer/mobile-native-chat-image-send'
|
||||
import type { MobileNativeChatRpcSender } from './mobile-native-chat-send'
|
||||
|
||||
// The condition tracked here — a bracketed image paste left sitting on the agent's
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from './mobile-native-chat-send'
|
||||
import { sendMobileTerminalQueryReply } from '../terminal/mobile-terminal-query-reply'
|
||||
import { useMobileDiffReviewSendActions } from './use-mobile-diff-review-send-actions'
|
||||
import { pasteMobileNativeChatImagePaths } from './mobile-native-chat-image-send'
|
||||
import { pasteMobileNativeChatImagePaths } from './native-chat/composer/mobile-native-chat-image-send'
|
||||
|
||||
vi.mock('react-native', () => ({ Keyboard: { dismiss: vi.fn() } }))
|
||||
vi.mock('../platform/haptics', () => ({ triggerError: vi.fn(), triggerSuccess: vi.fn() }))
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ import {
|
||||
View
|
||||
} from 'react-native'
|
||||
import { FileText, X } from 'lucide-react-native'
|
||||
import { colors, radii, spacing } from '../theme/mobile-theme'
|
||||
import { formatPreviewByteLength } from '../files/mobile-file-preview-response'
|
||||
import { colors, radii, spacing } from '../../../theme/mobile-theme'
|
||||
import { formatPreviewByteLength } from '../../../files/mobile-file-preview-response'
|
||||
import type { PendingNativeChatImage } from './mobile-native-chat-image-attachment'
|
||||
import type { PendingNativeChatFile } from './mobile-native-chat-file-attachment'
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { MobileFileTooLargeError, type PickedMobileFile } from '../platform/media-picker-contract'
|
||||
import {
|
||||
MobileFileTooLargeError,
|
||||
type PickedMobileFile
|
||||
} from '../../../platform/media-picker-contract'
|
||||
import {
|
||||
nativeChatTextWithFileReferences,
|
||||
uploadPickedNativeChatFiles,
|
||||
+6
-3
@@ -1,6 +1,9 @@
|
||||
import { formatNativeChatFileReference } from '../../../src/shared/agent-image-paste'
|
||||
import { MobileFileTooLargeError, type PickedMobileFile } from '../platform/media-picker-contract'
|
||||
import type { AgentSessionAttachmentUploadCommitResult } from '../../../src/shared/agent-session-attachments'
|
||||
import { formatNativeChatFileReference } from '../../../../../src/shared/agent-image-paste'
|
||||
import {
|
||||
MobileFileTooLargeError,
|
||||
type PickedMobileFile
|
||||
} from '../../../platform/media-picker-contract'
|
||||
import type { AgentSessionAttachmentUploadCommitResult } from '../../../../../src/shared/agent-session-attachments'
|
||||
|
||||
/** A file in the composer: its chip shows from the pick, and `path` arrives once the host stored it. */
|
||||
export type PendingNativeChatFile = {
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { RpcResponse, RpcSuccess } from '../transport/types'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import type { RpcResponse, RpcSuccess } from '../../../transport/types'
|
||||
import { uploadMobileNativeChatImages } from './mobile-native-chat-image-attachment'
|
||||
|
||||
function ok(id: string, result: unknown): RpcSuccess {
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { saveMobileClipboardImageAsTempFile } from './mobile-clipboard-image'
|
||||
import type { MobileClipboardImageRpcSender } from './mobile-clipboard-image-operations'
|
||||
import { saveMobileClipboardImageAsTempFile } from '../../mobile-clipboard-image'
|
||||
import type { MobileClipboardImageRpcSender } from '../../mobile-clipboard-image-operations'
|
||||
// Type-only import so this module (and its unit test) stays free of the expo/
|
||||
// react-native picker chain; the concrete `pickImage` is injected by the hook.
|
||||
import type { MobileImageSource, PickedMobileImage } from './mobile-image-source-picker'
|
||||
import type { MobileImageSource, PickedMobileImage } from '../../../platform/media-picker-contract'
|
||||
|
||||
/** A picked-and-uploaded image held in the native-chat composer until submit.
|
||||
* `path` is the host temp file pasted into the agent on send; `previewUri` is a
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { RpcResponse, RpcSuccess } from '../transport/types'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import type { RpcResponse, RpcSuccess } from '../../../transport/types'
|
||||
import { pasteMobileNativeChatImagePaths } from './mobile-native-chat-image-send'
|
||||
import { buildAgentTuiClearInputForText } from '../../../src/shared/agent-tui-input-clear'
|
||||
import { buildAgentTuiClearInputForText } from '../../../../../src/shared/agent-tui-input-clear'
|
||||
|
||||
function sendResult(accepted: boolean, id = 'send'): RpcSuccess {
|
||||
return { id, ok: true, result: { send: { accepted } }, _meta: { runtimeId: 'r' } }
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
import { agentImagePasteWrites } from '../../../src/shared/agent-image-paste'
|
||||
import { buildMobileImagePastePayload } from './mobile-clipboard-image'
|
||||
import { agentImagePasteWrites } from '../../../../../src/shared/agent-image-paste'
|
||||
import { buildMobileImagePastePayload } from '../../mobile-clipboard-image'
|
||||
import {
|
||||
MOBILE_NATIVE_CHAT_MIN_WRITE_TIMEOUT_MS,
|
||||
openMobileNativeChatSendBudget
|
||||
} from './mobile-native-chat-send'
|
||||
import { nativeChatTerminalWrite } from './mobile-session-write-operations'
|
||||
import type { MobileNativeChatRpcSender } from './mobile-native-chat-send'
|
||||
} from '../../mobile-native-chat-send'
|
||||
import { nativeChatTerminalWrite } from '../../mobile-session-write-operations'
|
||||
import type { MobileNativeChatRpcSender } from '../../mobile-native-chat-send'
|
||||
|
||||
// Give the agent TUI a beat to register each bracketed image paste before the
|
||||
// message text + Enter arrive, so the image attaches instead of being treated as
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import { useMediaPicker } from '../platform/media-picker'
|
||||
import { uploadMobileAgentSessionAttachment } from './mobile-agent-session-attachment-upload'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import { useMediaPicker } from '../../../platform/media-picker'
|
||||
import { uploadMobileAgentSessionAttachment } from '../../mobile-agent-session-attachment-upload'
|
||||
import { withScopeAttachments } from './mobile-native-chat-image-scope-state'
|
||||
import {
|
||||
uploadPickedNativeChatFiles,
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { createElement } from 'react'
|
||||
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import { useMobileNativeChatFileSearch } from './use-mobile-native-chat-file-search'
|
||||
|
||||
type SearchState = ReturnType<typeof useMobileNativeChatFileSearch>
|
||||
+4
-4
@@ -1,14 +1,14 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import {
|
||||
GenerationScopedRequestOwner,
|
||||
type RequestScope
|
||||
} from '../transport/generation-scoped-request-owner'
|
||||
} from '../../../transport/generation-scoped-request-owner'
|
||||
import {
|
||||
nativeChatFileInventoryRead,
|
||||
nativeChatFileSearchRead
|
||||
} from './mobile-session-read-operations'
|
||||
import { rankSuggestions } from './mobile-native-chat-autocomplete'
|
||||
} from '../../mobile-session-read-operations'
|
||||
import { rankSuggestions } from '../../mobile-native-chat-autocomplete'
|
||||
|
||||
const FILE_SEARCH_DEBOUNCE_MS = 120
|
||||
const FILE_SEARCH_RESULT_LIMIT = 16
|
||||
+6
-6
@@ -1,18 +1,18 @@
|
||||
import { createElement } from 'react'
|
||||
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
|
||||
import { buildAgentTuiClearInputForText } from '../../../src/shared/agent-tui-input-clear'
|
||||
import { buildAgentTuiClearInputForText } from '../../../../../src/shared/agent-tui-input-clear'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { RpcResponse, RpcSuccess } from '../transport/types'
|
||||
import { resetMobileNativeChatStaleInputForTests } from './mobile-native-chat-stale-input'
|
||||
import { resetMobileNativeChatTerminalWritesForTests } from './mobile-native-chat-terminal-write-lock'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import type { RpcResponse, RpcSuccess } from '../../../transport/types'
|
||||
import { resetMobileNativeChatStaleInputForTests } from '../../mobile-native-chat-stale-input'
|
||||
import { resetMobileNativeChatTerminalWritesForTests } from '../../mobile-native-chat-terminal-write-lock'
|
||||
import { useMobileNativeChatImageAttachments } from './use-mobile-native-chat-image-attachments'
|
||||
|
||||
// Stubbed at the seam the hook now holds, which keeps the real expo/react-native chain out of the
|
||||
// vitest transform (react-native ships Flow syntax rolldown cannot parse) and pins the call site:
|
||||
// a hook that went back to importing the picker module directly would load that chain and fail.
|
||||
const pick = vi.hoisted(() => vi.fn())
|
||||
vi.mock('../platform/media-picker', () => ({ useMediaPicker: () => ({ pickImages: pick }) }))
|
||||
vi.mock('../../../platform/media-picker', () => ({ useMediaPicker: () => ({ pickImages: pick }) }))
|
||||
|
||||
function ok(id: string, result: unknown): RpcSuccess {
|
||||
return { id, ok: true, result, _meta: { runtimeId: 'r' } }
|
||||
+8
-8
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import { buildAgentTuiClearInputForText } from '../../../src/shared/agent-tui-input-clear'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { ConnectionState } from '../transport/types'
|
||||
import type { MobileImageSource } from './mobile-image-source-picker'
|
||||
import { buildAgentTuiClearInputForText } from '../../../../../src/shared/agent-tui-input-clear'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import type { ConnectionState } from '../../../transport/types'
|
||||
import type { MobileImageSource } from '../../../platform/media-picker-contract'
|
||||
import {
|
||||
appendPendingNativeChatImages,
|
||||
type PendingNativeChatImage
|
||||
@@ -19,20 +19,20 @@ import {
|
||||
import {
|
||||
openMobileNativeChatSendBudget,
|
||||
type MobileNativeChatSendOutcome
|
||||
} from './mobile-native-chat-send'
|
||||
} from '../../mobile-native-chat-send'
|
||||
import {
|
||||
clearMobileNativeChatInputStale,
|
||||
healMobileNativeChatStaleInput,
|
||||
isMobileNativeChatInputStale,
|
||||
markMobileNativeChatInputStale
|
||||
} from './mobile-native-chat-stale-input'
|
||||
} from '../../mobile-native-chat-stale-input'
|
||||
import {
|
||||
acquireMobileNativeChatTerminalWrite,
|
||||
releaseMobileNativeChatTerminalWrite
|
||||
} from './mobile-native-chat-terminal-write-lock'
|
||||
} from '../../mobile-native-chat-terminal-write-lock'
|
||||
import { useMobileNativeChatImageUpload } from './use-mobile-native-chat-image-upload'
|
||||
import type { PendingNativeChatFile } from './mobile-native-chat-file-attachment'
|
||||
import type { StructuredMobileSendAttachment } from './use-mobile-structured-send-with-outcome'
|
||||
import type { StructuredMobileSendAttachment } from '../../use-mobile-structured-send-with-outcome'
|
||||
|
||||
type CurrentRef<T> = { readonly current: T }
|
||||
type ShowToast = (message: string, durationMs?: number) => void
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
import { useCallback, useLayoutEffect, useRef, useState } from 'react'
|
||||
import { CLIPBOARD_IMAGE_TOO_LARGE_ERROR } from '../../../src/shared/clipboard-image'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { ConnectionState } from '../transport/types'
|
||||
import { useMediaPicker } from '../platform/media-picker'
|
||||
import { CLIPBOARD_IMAGE_TOO_LARGE_ERROR } from '../../../../../src/shared/clipboard-image'
|
||||
import type { RpcClient } from '../../../transport/rpc-client'
|
||||
import type { ConnectionState } from '../../../transport/types'
|
||||
import { useMediaPicker } from '../../../platform/media-picker'
|
||||
import {
|
||||
ImageLibraryPermissionError,
|
||||
type MobileImageSource
|
||||
} from '../platform/media-picker-contract'
|
||||
} from '../../../platform/media-picker-contract'
|
||||
import {
|
||||
uploadMobileNativeChatImages,
|
||||
type PendingNativeChatImage
|
||||
@@ -142,7 +142,7 @@ vi.mock('./mobile-native-chat-permission-send', () => ({
|
||||
vi.mock('./use-mobile-native-chat-stop', () => ({
|
||||
useMobileNativeChatStop: () => vi.fn()
|
||||
}))
|
||||
vi.mock('./use-mobile-native-chat-file-search', () => ({
|
||||
vi.mock('./native-chat/composer/use-mobile-native-chat-file-search', () => ({
|
||||
useMobileNativeChatFileSearch: () => ({ nativeChatFilePaths: [], loadNativeChatFiles: vi.fn() })
|
||||
}))
|
||||
// Partial: the stale-input heal reaches the real transport through image-send,
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { MobileNativeChatTab } from './mobile-native-chat-eligibility'
|
||||
import type { StructuredAgentSessionHostSupport } from './mobile-structured-agent-session-host-support'
|
||||
import { useMobileNativeChatAskDismiss } from './use-mobile-native-chat-ask-dismiss'
|
||||
import { useMobileNativeChatDrafts } from './use-mobile-native-chat-drafts'
|
||||
import { useMobileNativeChatFileSearch } from './use-mobile-native-chat-file-search'
|
||||
import { useMobileNativeChatFileSearch } from './native-chat/composer/use-mobile-native-chat-file-search'
|
||||
import { useMobileNativeChatMessageSend } from './use-mobile-native-chat-message-send'
|
||||
import { mobileNativeChatStreamPreview } from './mobile-native-chat-streaming-gate'
|
||||
import { useMobileNativeChatSessionOptionController } from './use-mobile-native-chat-session-option-controller'
|
||||
|
||||
@@ -5,9 +5,9 @@ import {
|
||||
countUserTextOccurrences,
|
||||
findLandedImagePreviewEchoes,
|
||||
mergeSentImagePreviews,
|
||||
migrateImagePreviewMessageIds,
|
||||
normalizeReconcileText
|
||||
migrateImagePreviewMessageIds
|
||||
} from './mobile-native-chat-draft-reconcile'
|
||||
import { normalizeNativeChatUserText as normalizeReconcileText } from '../../../src/shared/native-chat-image-transcript-markers'
|
||||
import { useMobileNativeChatUnconfirmedSends } from './use-mobile-native-chat-unconfirmed-sends'
|
||||
import { rebaseMobileNativeChatPendingBaselines } from './mobile-native-chat-pending-baseline'
|
||||
import { retireLandedMobileNativeChatPending } from './mobile-native-chat-pending-retirement'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useMemo } from 'react'
|
||||
import type { AgentSessionConversationCommand } from '../../../src/shared/agent-session/agent-session-conversation-command'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import type { MobileNativeChatStructuredComposer } from './MobileNativeChatComposer'
|
||||
import type { MobileNativeChatFileAttachments } from './use-mobile-native-chat-file-attachments'
|
||||
import type { MobileNativeChatFileAttachments } from './native-chat/composer/use-mobile-native-chat-file-attachments'
|
||||
import { useMobileStructuredSessionCommands } from './use-mobile-structured-session-commands'
|
||||
|
||||
const NO_COMMANDS: readonly AgentSessionConversationCommand[] = []
|
||||
|
||||
@@ -7,11 +7,11 @@ import { useMobileImageAttachment } from './use-mobile-image-attachment'
|
||||
import {
|
||||
useMobileNativeChatImageAttachments,
|
||||
type MobileNativeChatImageAttachments
|
||||
} from './use-mobile-native-chat-image-attachments'
|
||||
} from './native-chat/composer/use-mobile-native-chat-image-attachments'
|
||||
import {
|
||||
useMobileNativeChatFileAttachments,
|
||||
type MobileNativeChatFileAttachments
|
||||
} from './use-mobile-native-chat-file-attachments'
|
||||
} from './native-chat/composer/use-mobile-native-chat-file-attachments'
|
||||
|
||||
type CurrentRef<T> = { readonly current: T }
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { sendMobileStructuredAgentSessionMessage } from './mobile-structured-age
|
||||
import type { MobileStructuredSends } from './use-mobile-structured-sends'
|
||||
import { structuredSessionOperationId } from './structured-session-operation-id'
|
||||
import { timeoutForDeadline } from './mobile-structured-agent-session-rpc'
|
||||
import { nativeChatTextWithFileReferences } from './mobile-native-chat-file-attachment'
|
||||
import { nativeChatTextWithFileReferences } from './native-chat/composer/mobile-native-chat-file-attachment'
|
||||
import {
|
||||
actionableStructuredApproval,
|
||||
actionableStructuredQuestion
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type * as MobileNativeChatImageAttachment from '../../../session/native-chat/composer/mobile-native-chat-image-attachment'
|
||||
import type * as MobileNativeChatImageSend from '../../../session/native-chat/composer/mobile-native-chat-image-send'
|
||||
import type { MountAdapter } from '../recording-scenario'
|
||||
import { mountFixture } from '../recorder-fixture-shape'
|
||||
import type { operationModuleLoader } from '../operation-module-loader'
|
||||
@@ -80,9 +82,9 @@ export function clipboardImageMountAdapters(
|
||||
}
|
||||
},
|
||||
'nativeChat.image-upload': ({ client, effect }) => {
|
||||
const upload = modules.load<
|
||||
typeof import('../../../session/mobile-native-chat-image-attachment')
|
||||
>('mobile/src/session/mobile-native-chat-image-attachment.ts').uploadMobileNativeChatImages
|
||||
const upload = modules.load<typeof MobileNativeChatImageAttachment>(
|
||||
'mobile/src/session/native-chat/composer/mobile-native-chat-image-attachment.ts'
|
||||
).uploadMobileNativeChatImages
|
||||
let uploaded: unknown = 'unuploaded'
|
||||
let failure: unknown = null
|
||||
return {
|
||||
@@ -116,8 +118,8 @@ export function clipboardImageMountAdapters(
|
||||
}
|
||||
},
|
||||
'nativeChat.image-paste': ({ client }) => {
|
||||
const paste = modules.load<typeof import('../../../session/mobile-native-chat-image-send')>(
|
||||
'mobile/src/session/mobile-native-chat-image-send.ts'
|
||||
const paste = modules.load<typeof MobileNativeChatImageSend>(
|
||||
'mobile/src/session/native-chat/composer/mobile-native-chat-image-send.ts'
|
||||
).pasteMobileNativeChatImagePaths
|
||||
let pasted: unknown = 'unpasted'
|
||||
let failure: unknown = null
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type * as MobileNativeChatFileSearch from '../../../session/native-chat/composer/use-mobile-native-chat-file-search'
|
||||
import { hookMount, performHookAction } from '../hook-mount'
|
||||
import type { MountOptions } from '../mounted-operation-module'
|
||||
import { operationModuleLoader } from '../operation-module-loader'
|
||||
@@ -10,9 +11,9 @@ export function fileInventoryMountAdapters(
|
||||
): Record<string, MountAdapter> {
|
||||
return {
|
||||
'workspace.file-inventory': ({ client }) => {
|
||||
const useSearch = modules.load<
|
||||
typeof import('../../../session/use-mobile-native-chat-file-search')
|
||||
>('mobile/src/session/use-mobile-native-chat-file-search.ts').useMobileNativeChatFileSearch
|
||||
const useSearch = modules.load<typeof MobileNativeChatFileSearch>(
|
||||
'mobile/src/session/native-chat/composer/use-mobile-native-chat-file-search.ts'
|
||||
).useMobileNativeChatFileSearch
|
||||
const operations = options.reference
|
||||
? modules
|
||||
.load('mobile/src/session/native-host-session-native-chat-operations.ts')
|
||||
|
||||
@@ -513,7 +513,7 @@ describe('loader write fence', () => {
|
||||
// the scan found no holder and no loader to look inside.
|
||||
expect(
|
||||
holders.map(({ path }) => relative(mobileRoot, path).split(/[/\\]/).join('/'))
|
||||
).toContain('src/session/use-mobile-native-chat-file-search.ts')
|
||||
).toContain('src/session/native-chat/composer/use-mobile-native-chat-file-search.ts')
|
||||
expect(
|
||||
holders.reduce((total, { path, source }) => total + loaders(path, source).length, 0)
|
||||
).toBeGreaterThan(0)
|
||||
|
||||
Reference in New Issue
Block a user