fix(mobile): accept sentence-final cited paths

This commit is contained in:
Brennan Benson
2026-08-12 20:05:53 -07:00
parent 8b89629c48
commit 4316d9b169
2 changed files with 41 additions and 1 deletions
@@ -79,6 +79,38 @@ describe('nativeChatTranscriptIncludesPath', () => {
expect(readTranscript).not.toHaveBeenCalled()
})
it('accepts a path followed by a sentence-final period', async () => {
const readTranscript = vi.fn(async () => ({
messages: [message('assistant', 'Open /tmp/orca-pr14166-external.txt.')]
}))
await expect(
nativeChatTranscriptIncludesPath({
tabs: [terminalTab()],
context: { tabId: 'tab-1', sessionId: 'session-1' },
pathText: '/tmp/orca-pr14166-external.txt',
absolutePath: '/tmp/orca-pr14166-external.txt',
readTranscript
})
).resolves.toBe(true)
})
it('does not accept a longer filename sharing the requested path prefix', async () => {
const readTranscript = vi.fn(async () => ({
messages: [message('assistant', 'Open /tmp/orca-pr14166-external.txt.backup')]
}))
await expect(
nativeChatTranscriptIncludesPath({
tabs: [terminalTab()],
context: { tabId: 'tab-1', sessionId: 'session-1' },
pathText: '/tmp/orca-pr14166-external.txt',
absolutePath: '/tmp/orca-pr14166-external.txt',
readTranscript
})
).resolves.toBe(false)
})
it('does not treat user-authored transcript text as agent provenance', async () => {
const readTranscript = vi.fn(async () => ({
messages: [message('user', 'Please open /etc/passwd')]
@@ -18,6 +18,14 @@ type TranscriptRead = (args: {
limit: number
}) => Promise<{ messages: NativeChatMessage[] } | { error: string }>
function transcriptTextIncludesPath(text: string, pathText: string, absolutePath: string): boolean {
if (recentTerminalOutputIncludesPath(text, pathText, absolutePath)) {
return true
}
// Mobile excludes a sentence-final period from the tappable path span.
return recentTerminalOutputIncludesPath(text, `${pathText}.`, `${absolutePath}.`)
}
export async function nativeChatTranscriptIncludesPath(args: {
tabs: readonly RuntimeMobileSessionClientTab[]
context: RuntimeNativeChatFileContext
@@ -57,7 +65,7 @@ export async function nativeChatTranscriptIncludesPath(args: {
message.blocks.some(
(block) =>
block.type === 'text' &&
recentTerminalOutputIncludesPath(block.text, args.pathText, args.absolutePath)
transcriptTextIncludesPath(block.text, args.pathText, args.absolutePath)
)
)
} catch {