Files
orca/mobile/src/session/mobile-markdown-disk-fallback.ts
T
Jinwoo Hong fe34acda3b fix(mobile): truncate oversize markdown reads instead of failing them (#23676)
* fix(mobile): truncate oversize markdown reads instead of failing them

The desktop bridge refused markdown over a private 512 KiB cap with
file_too_large, which reached the phone as a generic runtime_error that
the reader discarded, so a 632 KB file showed "Couldn't load markdown".
Reads now return a UTF-8-boundary prefix under one shared 2 MiB budget,
marked truncated with the full byteLength and read-only. The phone shows
the truncation like file tabs do and maps refusal codes to real copy, so
an older desktop's refusal reads "File too large for mobile preview".

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb

* test(mobile): pin that a truncated markdown read is never editable

The read budget sits above the edit budget, so every truncated document is
already read-only as file_too_large. Pin that ordering so a future budget
change cannot make a prefix editable, and name the constant as the markdown
preview budget, separate from the file preview's own.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb

* test(mobile): refuse saves from a truncated markdown read

A phone holding a truncated prefix must not write it back; the 256 KiB
save guard refuses it as file_too_large before any version check. The
shared budget test shrinks to the ordering it pins and names the bridge
test as the behavioural pin.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb

* refactor(mobile): tighten markdown truncation types and measure once

The read truncation measures the document once. The disk fallback drops
its truncated-only read-only text, which the status line never showed,
and both truncation fields are optional there. A markdown doc's flag is
only ever true, and the schema comment names the hook, not line numbers.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb

* docs(mobile): drop a stale disk-fallback comment

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb

* chore: retrigger CI after #23675 landed on main

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-28 16:58:15 -04:00

34 lines
1.0 KiB
TypeScript

import type { RpcFailure } from '../transport/types'
import type { MarkdownDocState } from './mobile-session-route-types'
const RENDERER_UNAVAILABLE = 'renderer_unavailable'
export function shouldReadMarkdownFromDiskAfterReadTabFailure(response: RpcFailure): boolean {
return (
response.error.code === RENDERER_UNAVAILABLE ||
(response.error.code === 'runtime_error' && response.error.message === RENDERER_UNAVAILABLE)
)
}
export function buildMarkdownDiskFallbackDoc(args: {
content: string
truncated?: boolean
byteLength?: number
tabIsDirty: boolean
}): Extract<MarkdownDocState, { status: 'ready' }> {
const readOnlyReason = args.tabIsDirty
? 'Desktop has unsaved changes. Showing disk content.'
: 'Editing needs Orca desktop running.'
return {
status: 'ready',
content: args.content,
localContent: args.content,
baseVersion: '',
isDirty: false,
editable: false,
stale: args.tabIsDirty,
readOnlyReason,
...(args.truncated ? { truncated: true, byteLength: args.byteLength } : {})
}
}