refactor(shared): group native chat visual contracts (#34296)

This commit is contained in:
Neil
2026-10-27 00:03:29 -07:00
committed by GitHub
parent 30872835cd
commit 1dec1ebc35
42 changed files with 41 additions and 41 deletions
+4 -4
View File
@@ -12636,10 +12636,10 @@
"src/shared/native-chat-turn-status.test.ts": 52,
"src/shared/native-chat-unverifiable-turn-status.test.ts": 111,
"src/shared/native-chat-upgrade-tip-audience.test.ts": 41,
"src/shared/native-chat-visual-directive.test.ts": 45,
"src/shared/native-chat-visual-height-governor.test.ts": 141,
"src/shared/native-chat-visual-shell.reader-scroll.test.ts": 188,
"src/shared/native-chat-visual-shell.test.ts": 202,
"src/shared/native-chat/native-chat-visual-directive.test.ts": 45,
"src/shared/native-chat/native-chat-visual-height-governor.test.ts": 141,
"src/shared/native-chat/native-chat-visual-shell.reader-scroll.test.ts": 188,
"src/shared/native-chat/native-chat-visual-shell.test.ts": 202,
"src/shared/native-chat-work-run.test.ts": 127,
"src/shared/native-chat/native-chat-command-language.test.ts": 42,
"src/shared/native-chat/native-chat-orca-stop-cut.test.ts": 198,
@@ -32,7 +32,7 @@ beforeAll(async () => {
}
// Import behind dependency gate: transforming mobile/ reads Expo tsconfig absent from root-only shards.
;({ buildNativeChatVisualDocument, NATIVE_CHAT_VISUAL_PONG_TYPE: pongType } =
await import('../../../src/shared/native-chat-visual-shell'))
await import('../../../src/shared/native-chat/native-chat-visual-shell'))
;({ buildMobileNativeChatVisualHostDocument } =
await import('../../../mobile/src/session/mobile-native-chat-visual-host-document'))
const header = await readShellCsp()
+1 -1
View File
@@ -191,7 +191,7 @@ const MOBILE_WEB_APP_PREFIXES = [
'mobile/pnpm-lock.yaml',
'mobile/modules/orca-mobile-web-shell/',
// Chat visuals on both mobile surfaces are built from it; their in-page links check runs here.
'src/shared/native-chat-visual-shell'
'src/shared/native-chat/native-chat-visual-shell'
]
function changesMobileWebApp(changedFiles) {
+1 -1
View File
@@ -346,7 +346,7 @@ describe('per-job path classification', () => {
'mobile/app/h/[hostId]/index.tsx',
'mobile/src/transport/client-context.web.tsx',
'mobile/modules/orca-mobile-web-shell/ios/MobileWebShellCsp.swift',
'src/shared/native-chat-visual-shell.ts',
'src/shared/native-chat/native-chat-visual-shell.ts',
// The vendored Expo module the page resolves a .web.ts out of.
'mobile/packages/expo-two-way-audio/src/ExpoTwoWayAudioModule.web.ts'
]) {
+1 -1
View File
@@ -6,7 +6,7 @@ import { renderBlocks, type MarkdownBlockContext } from './mobile-markdown-block
import { MarkdownText } from './mobile-markdown-text'
import { MarkdownTextContext, type MarkdownTextSetup } from './mobile-markdown-text-setup'
import { useMobileMarkdownTree } from './use-mobile-markdown-tree'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat-visual-directive'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat/native-chat-visual-directive'
type Props = {
content?: string
+1 -1
View File
@@ -2,7 +2,7 @@ import { agentNoUpdateLabel } from '../../../src/shared/agent-row-decay-state'
import { memo } from 'react'
import { Pressable, StyleSheet, Text, View } from 'react-native'
import type { RuntimeWorktreeAgentRow } from '../../../src/shared/runtime-types'
import { withoutNativeChatVisualDirectiveLines } from '../../../src/shared/native-chat-visual-directive'
import { withoutNativeChatVisualDirectiveLines } from '../../../src/shared/native-chat/native-chat-visual-directive'
import { colors, spacing } from '../theme/mobile-theme'
import {
agentDisplayLabel,
@@ -8,7 +8,7 @@ import {
type StyleProp,
type TextStyle
} from 'react-native'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat-visual-directive'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat/native-chat-visual-directive'
import { isMobileMermaidLanguage } from './mobile-mermaid-language'
import { mobileMarkdownTableColumnWidths } from './mobile-markdown-table-columns'
import { mobileMarkdownVisualPlaceholderIndex } from './mobile-markdown-visual-lines'
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import { NATIVE_CHAT_VISUAL_MAX_PER_MESSAGE } from '../../../src/shared/native-chat-visual-directive'
import { NATIVE_CHAT_VISUAL_MAX_PER_MESSAGE } from '../../../src/shared/native-chat/native-chat-visual-directive'
import { parseMobileMarkdownTree, plainText } from './mobile-markdown-tree'
import {
mobileMarkdownVisualPlaceholderIndex,
@@ -3,7 +3,7 @@ import {
NATIVE_CHAT_VISUAL_MAX_PER_MESSAGE,
parseNativeChatVisualDirectiveLine,
type NativeChatVisualDirective
} from '../../../src/shared/native-chat-visual-directive'
} from '../../../src/shared/native-chat/native-chat-visual-directive'
import { mobileMarkdownCodeLines } from './mobile-markdown-tree'
// Private-use delimiters, as the preview normalizer's own code placeholders use.
const PLACEHOLDER_PREFIX = '\uE000ORCA_VISUAL_'
@@ -1,6 +1,6 @@
import type { Root } from 'mdast'
import { useMemo } from 'react'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat-visual-directive'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat/native-chat-visual-directive'
import { parseMobileMarkdownTree } from './mobile-markdown-tree'
import { protectMobileMarkdownVisualLines } from './mobile-markdown-visual-lines'
+1 -1
View File
@@ -11,7 +11,7 @@ import {
AGENT_SESSION_HOST_STATUS_COPY,
isAgentSessionHostStatusPresentation
} from '../../../src/shared/agent-session-host-status-rows'
import { withoutPendingNativeChatVisualDirectiveTail } from '../../../src/shared/native-chat-visual-directive'
import { withoutPendingNativeChatVisualDirectiveTail } from '../../../src/shared/native-chat/native-chat-visual-directive'
import { isAgentSessionAttachmentStorePath } from '../../../src/shared/agent-session-attachments'
import { MobileNativeChatRowOverlaysContext } from './mobile-native-chat-row-overlays'
import { isRenderableImageUri, readStoredChatImage } from './mobile-native-chat-image-preview'
@@ -1,7 +1,7 @@
import { memo, useCallback, useMemo, useState } from 'react'
import { ActivityIndicator, Modal, Pressable, StyleSheet, Text, View } from 'react-native'
import { Maximize2, X } from 'lucide-react-native'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat-visual-directive'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat/native-chat-visual-directive'
import { useWindowSafeAreaInsets } from '../layout/side-safe-area'
import { colors, radii, spacing, typography } from '../theme/mobile-theme'
import type { MobileNativeChatVisualSource } from './mobile-native-chat-visual-read'
@@ -1,6 +1,6 @@
import { memo, useMemo } from 'react'
import { StyleSheet, View } from 'react-native'
import { buildNativeChatVisualDocument } from '../../../src/shared/native-chat-visual-shell'
import { buildNativeChatVisualDocument } from '../../../src/shared/native-chat/native-chat-visual-shell'
import type { MobileNativeChatVisualHostMode } from './mobile-native-chat-visual-host-document'
import { MOBILE_NATIVE_CHAT_VISUAL_THEME } from './mobile-native-chat-visual-theme'
@@ -3,7 +3,7 @@ import {
isAgentSessionHostStatusPresentation
} from '../../../src/shared/agent-session-host-status-rows'
import { isTextBlock } from '../../../src/shared/native-chat-types'
import { withoutNativeChatVisualDirectiveLines } from '../../../src/shared/native-chat-visual-directive'
import { withoutNativeChatVisualDirectiveLines } from '../../../src/shared/native-chat/native-chat-visual-directive'
import type { NativeChatMessage } from '../../../src/shared/native-chat-types'
export function nativeChatMessagePlainText(
@@ -1,5 +1,5 @@
import { createContext, type ReactNode } from 'react'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat-visual-directive'
import type { NativeChatVisualDirective } from '../../../src/shared/native-chat/native-chat-visual-directive'
export type MobileNativeChatVisualRender = (
directive: NativeChatVisualDirective,
@@ -5,7 +5,7 @@ import {
NATIVE_CHAT_VISUAL_PONG_TIMEOUT_MS,
NATIVE_CHAT_VISUAL_PONG_TYPE,
NATIVE_CHAT_VISUAL_SIZE_TYPE
} from '../../../src/shared/native-chat-visual-shell'
} from '../../../src/shared/native-chat/native-chat-visual-shell'
import { inlineScriptLiteral } from '../components/inline-script-json'
/** `inline` sizes the frame to the height the app applies; `fullscreen` fills the screen and scrolls. */
@@ -1,5 +1,5 @@
import { z } from 'zod'
import { NATIVE_CHAT_VISUAL_MAX_BYTES } from '../../../src/shared/native-chat-visual-directive'
import { NATIVE_CHAT_VISUAL_MAX_BYTES } from '../../../src/shared/native-chat/native-chat-visual-directive'
import { bindDeferredRpcOperation, defineRpcOperation } from '../transport/rpc-operation'
import { rpcResultVariant } from '../transport/rpc-operation-result-reader'
import { isMobileMethodUnavailableError } from '../transport/mobile-method-unavailable'
@@ -1,4 +1,4 @@
import type { NativeChatVisualTheme } from '../../../src/shared/native-chat-visual-shell'
import type { NativeChatVisualTheme } from '../../../src/shared/native-chat/native-chat-visual-shell'
import { colors, radii } from '../theme/mobile-theme'
// Match desktop’s dark chart tokens; initialize visual styles before author content runs.
@@ -1,5 +1,5 @@
import { sliceAtCodeUnitLimit } from '../../shared/surrogate-safe-text-slice'
import { withoutNativeChatVisualDirectiveLines } from '../../shared/native-chat-visual-directive'
import { withoutNativeChatVisualDirectiveLines } from '../../shared/native-chat/native-chat-visual-directive'
export { sliceAtCodeUnitLimit }
@@ -3,7 +3,7 @@ import { chmod, mkdir, mkdtemp, rm, symlink, writeFile, link } from 'node:fs/pro
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import { NATIVE_CHAT_VISUAL_MAX_BYTES } from '../../shared/native-chat-visual-directive'
import { NATIVE_CHAT_VISUAL_MAX_BYTES } from '../../shared/native-chat/native-chat-visual-directive'
import { nativeChatScratchFolderFor } from './native-chat-scratch-folder'
import { nativeChatVisualRevision, readNativeChatVisualFile } from './native-chat-visual-file-read'
@@ -7,7 +7,7 @@ import { basename, dirname, join } from 'node:path'
import {
NATIVE_CHAT_VISUAL_MAX_BYTES,
isNativeChatVisualFileName
} from '../../shared/native-chat-visual-directive'
} from '../../shared/native-chat/native-chat-visual-directive'
import type {
AgentSessionReadVisualResult,
AgentSessionVisualReadError
@@ -6,8 +6,8 @@ import {
NATIVE_CHAT_VISUAL_MAX_BYTES,
NATIVE_CHAT_VISUAL_MAX_PER_MESSAGE,
parseNativeChatVisualDirectiveLine
} from '../../shared/native-chat-visual-directive'
import { NATIVE_CHAT_VISUAL_THEME_TOKENS } from '../../shared/native-chat-visual-shell'
} from '../../shared/native-chat/native-chat-visual-directive'
import { NATIVE_CHAT_VISUAL_THEME_TOKENS } from '../../shared/native-chat/native-chat-visual-shell'
import { ORCAD_NATIVE_CHAT_VISUALS_ARTIFACTS } from '../../shared/orcad-artifacts'
import {
createNativeChatVisualsDelivery,
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { PLUGIN_PANEL_FRAME_NAME_PREFIX } from '../../shared/plugins/plugin-panel-bridge'
import { NATIVE_CHAT_VISUAL_FRAME_NAME_PREFIX } from '../../shared/native-chat-visual-shell'
import { NATIVE_CHAT_VISUAL_FRAME_NAME_PREFIX } from '../../shared/native-chat/native-chat-visual-shell'
import { HostFrameNavigationRegistry, hostFrameKindForName } from './host-frame-navigation-guard'
function frame(input: { id: number; name?: string; url?: string }) {
@@ -1,5 +1,5 @@
import type { WebContents, WebFrameMain } from 'electron'
import { NATIVE_CHAT_VISUAL_FRAME_NAME_PREFIX } from '../../shared/native-chat-visual-shell'
import { NATIVE_CHAT_VISUAL_FRAME_NAME_PREFIX } from '../../shared/native-chat/native-chat-visual-shell'
import { PLUGIN_PANEL_FRAME_NAME_PREFIX } from '../../shared/plugins/plugin-panel-bridge'
type NavigationFrame = Pick<WebFrameMain, 'frameTreeNodeId' | 'isDestroyed' | 'name'>
@@ -14,7 +14,7 @@ import CommentMarkdown, {
} from '@/components/sidebar/CommentMarkdown'
import { createDocumentCommentMarkdownComponents } from '@/components/sidebar/comment-markdown-element-renderers'
import { cn } from '@/lib/utils'
import { withoutPendingNativeChatVisualDirectiveTail } from '../../../../shared/native-chat-visual-directive'
import { withoutPendingNativeChatVisualDirectiveTail } from '../../../../shared/native-chat/native-chat-visual-directive'
import { NativeChatMarkdownRowKeyContext } from './native-chat-disclosure-store'
import { useNativeChatVisualMarkdownExtension } from './native-chat-visual-markdown-extension'
import { useNativeChatFileLinkExists } from './use-native-chat-file-link-existence'
@@ -6,7 +6,7 @@ import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-libra
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import type * as TranscriptChromeModule from './NativeChatTranscriptChrome'
import type { NativeChatMessage } from '../../../../shared/native-chat-types'
import { NATIVE_CHAT_VISUAL_READER_SCROLL_TYPE } from '../../../../shared/native-chat-visual-shell'
import { NATIVE_CHAT_VISUAL_READER_SCROLL_TYPE } from '../../../../shared/native-chat/native-chat-visual-shell'
const callRuntimeRpc = vi.fn()
vi.mock('@/runtime/runtime-rpc-client', () => ({
@@ -7,7 +7,7 @@ import type { NativeChatBlock } from '../../../../shared/native-chat-types'
import { NativeChatCopyButton } from './NativeChatCopyButton'
import { NativeChatMessageTimestamp } from './NativeChatMessageTimestamp'
import { nativeChatProviderFrameSummary } from '../../../../shared/native-chat/native-chat-provider-frame-summary'
import { withoutNativeChatVisualDirectiveLines } from '../../../../shared/native-chat-visual-directive'
import { withoutNativeChatVisualDirectiveLines } from '../../../../shared/native-chat/native-chat-visual-directive'
import { PanZoomImageDialog } from '@/components/editor/PanZoomImageDialog'
import {
getLocalImageCacheKey,
@@ -14,7 +14,7 @@ import {
NATIVE_CHAT_VISUAL_READER_SCROLL_TYPE,
NATIVE_CHAT_VISUAL_SIZE_TYPE,
NATIVE_CHAT_VISUAL_THEME_TYPE
} from '../../../../shared/native-chat-visual-shell'
} from '../../../../shared/native-chat/native-chat-visual-shell'
const openHttpLink = vi.fn()
vi.mock('@/lib/http-link-routing', () => ({
@@ -8,9 +8,9 @@ import {
nativeChatVisualThemeMessage,
readNativeChatVisualFrameMessage,
readNativeChatVisualPong
} from '../../../../shared/native-chat-visual-shell'
} from '../../../../shared/native-chat/native-chat-visual-shell'
import type { NativeChatVisualDocument } from './native-chat-visual-read-client'
import { createNativeChatVisualHeightGovernor } from '../../../../shared/native-chat-visual-height-governor'
import { createNativeChatVisualHeightGovernor } from '../../../../shared/native-chat/native-chat-visual-height-governor'
import type { ReaderGesture } from './native-chat-autoscroll'
import { useNativeChatVisualTheme } from './use-native-chat-visual-theme'
import { useWebviewDragPassthroughActive } from '../browser-pane/host-guest/use-webview-drag-passthrough-active'
@@ -1,6 +1,6 @@
import type { NativeChatMessage } from '../../../../shared/native-chat-types'
import { deriveNativeChatRowContent } from '../../../../shared/native-chat-row-content'
import { withoutNativeChatVisualDirectiveLines } from '../../../../shared/native-chat-visual-directive'
import { withoutNativeChatVisualDirectiveLines } from '../../../../shared/native-chat/native-chat-visual-directive'
import { nativeChatBlocksInOwnWords } from './native-chat-stopped-before-start-row'
import type { NativeChatTranscriptSlot } from './native-chat-transcript-slots'
@@ -4,7 +4,7 @@ import type { CommentMarkdownExtension } from '@/components/sidebar/CommentMarkd
import {
NATIVE_CHAT_VISUAL_TITLE_MAX_LENGTH,
isNativeChatVisualFileName
} from '../../../../shared/native-chat-visual-directive'
} from '../../../../shared/native-chat/native-chat-visual-directive'
import { NativeChatInlineVisual } from './NativeChatInlineVisual'
import type { NativeChatVisualOwner } from './native-chat-visual-owner'
import { useNativeChatVisualOwner } from './native-chat-visual-owner'
@@ -15,7 +15,7 @@ import {
NATIVE_CHAT_VISUAL_DIRECTIVE_MAX_LINE_LENGTH,
NATIVE_CHAT_VISUAL_MAX_PER_MESSAGE,
parseNativeChatVisualDirectiveLine
} from '../../../../shared/native-chat-visual-directive'
} from '../../../../shared/native-chat/native-chat-visual-directive'
const TOKEN_TYPE = 'nativeChatVisual'
const COLON = 58
@@ -2,7 +2,7 @@ import { useEffect, useState, type RefObject } from 'react'
import {
NATIVE_CHAT_VISUAL_THEME_TOKENS,
type NativeChatVisualTheme
} from '../../../../shared/native-chat-visual-shell'
} from '../../../../shared/native-chat/native-chat-visual-shell'
// Visuals inherit the chat’s appearance scope, which can differ from the app root.
const SCOPED_SOURCES: Partial<Record<string, readonly string[]>> = {
@@ -1,4 +1,4 @@
import { PANEL_DESIGN_TOKEN_ALLOWLIST } from './plugins/plugin-panel-shell'
import { PANEL_DESIGN_TOKEN_ALLOWLIST } from '../plugins/plugin-panel-shell'
/** Shared Electron-free sandbox document. Parse CSP before visual markup so later HTML cannot loosen it.
* Allow pinned-CDN scripts/styles/fonts/images only; block fetch/sockets/frames/forms. Allowed-CDN requests can still carry data: disclosed accepted risk, not a no-egress guarantee. */
@@ -1,5 +1,5 @@
import { z } from 'zod'
import { isNativeChatVisualFileName } from '../native-chat-visual-directive'
import { isNativeChatVisualFileName } from '../native-chat/native-chat-visual-directive'
import { SessionId } from './structured-agent-session-identifiers'
// Read visuals on their owning host; accept bare filenames, never another host’s paths.
@@ -11,7 +11,7 @@ import { agentJournalSubmissionKey } from './agent-session-journal-item-key'
import { isRootAgentJournalItem } from './agent-session-journal-producer'
import { readAgentJournalTurn, readAgentJournalTurnOutcome } from './agent-session-turn-record'
import { classifyDispatchRejection } from './structured-agent-session-dispatch-rejection'
import { withoutNativeChatVisualDirectiveLines } from './native-chat-visual-directive'
import { withoutNativeChatVisualDirectiveLines } from './native-chat/native-chat-visual-directive'
import { isUnansweredStructuredAgentSessionDispatch } from './structured-agent-session-unanswered-dispatch'
import {
isStructuredAgentSessionCommandEntry,