mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 01:21:43 +00:00
fix(tui): address code review findings
Medium fixes: - textInput.tsx: prevent silent data loss when async paste resolves after user types — fall back to raw text insert at current cursor instead of dropping the content entirely - useComposerState.ts: tighten looksLikeDroppedPath to require a second '/' or '.' for bare absolute paths, avoiding unnecessary RPC round-trips for pasted text like /api or /help - useComposerState.ts: add cross-reference comment linking to the canonical _detect_file_drop() in cli.py - osc52.ts: add 500ms timeout via Promise.race so terminals that do not support OSC52 clipboard queries cannot hang paste Low fixes: - terminalSetup.ts: export isRemoteShellSession and reuse in terminalParity.ts and useComposerState.ts (was inlined 3 times) - useComposerState.ts: extract insertAtCursor helper, replacing 3 copies of the lead/tail spacing logic - useComposerState.ts: remove redundant gw from handleTextPaste useCallback dependency array - terminalSetup.test.ts: add EACCES (read-only keybindings.json) and unterminated block comment test coverage
This commit is contained in:
parent
bc9927dc50
commit
c9e8d82ef4
7 changed files with 95 additions and 42 deletions
|
|
@ -45,6 +45,13 @@ describe('terminalSetup helpers', () => {
|
|||
const input = '[{"key":"a","args":{"text":"// not a comment"}}]'
|
||||
expect(JSON.parse(stripJsonComments(input))).toEqual([{ key: 'a', args: { text: '// not a comment' } }])
|
||||
})
|
||||
|
||||
it('handles unterminated block comments gracefully', () => {
|
||||
const input = '[{"key":"a"} /* never closed'
|
||||
const stripped = stripJsonComments(input)
|
||||
// The unterminated comment is consumed to end-of-file; the remainder is parseable
|
||||
expect(stripped).toBe('[{"key":"a"} ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('configureTerminalKeybindings', () => {
|
||||
|
|
@ -114,6 +121,23 @@ describe('configureTerminalKeybindings', () => {
|
|||
expect(copyFile).toHaveBeenCalledTimes(1) // backup created before writing
|
||||
})
|
||||
|
||||
it('reports error when keybindings.json is not readable (EACCES)', async () => {
|
||||
const mkdir = vi.fn().mockResolvedValue(undefined)
|
||||
const readFile = vi.fn().mockRejectedValue(Object.assign(new Error('permission denied'), { code: 'EACCES' }))
|
||||
const writeFile = vi.fn().mockResolvedValue(undefined)
|
||||
const copyFile = vi.fn().mockResolvedValue(undefined)
|
||||
|
||||
const result = await configureTerminalKeybindings('vscode', {
|
||||
fileOps: { copyFile, mkdir, readFile, writeFile },
|
||||
homeDir: '/Users/me',
|
||||
platform: 'darwin'
|
||||
})
|
||||
|
||||
expect(result.success).toBe(false)
|
||||
expect(result.message).toContain('Failed to read')
|
||||
expect(writeFile).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('auto-detects the current IDE terminal', async () => {
|
||||
const mkdir = vi.fn().mockResolvedValue(undefined)
|
||||
const readFile = vi.fn().mockRejectedValue(Object.assign(new Error('missing'), { code: 'ENOENT' }))
|
||||
|
|
|
|||
|
|
@ -40,10 +40,16 @@ describe('looksLikeDroppedPath', () => {
|
|||
expect(looksLikeDroppedPath('http://localhost/file.pdf')).toBe(false)
|
||||
})
|
||||
|
||||
it('treats leading-slash strings as potential paths (server-side validates)', () => {
|
||||
// The heuristic is intentionally broad — starts with / could be a path.
|
||||
// Server-side image.attach / input.detect_drop does real validation.
|
||||
expect(looksLikeDroppedPath('/help')).toBe(true)
|
||||
expect(looksLikeDroppedPath('/model sonnet')).toBe(true)
|
||||
it('rejects short slash-like strings without path structure', () => {
|
||||
// No second '/' or '.' → not a plausible file path
|
||||
expect(looksLikeDroppedPath('/help')).toBe(false)
|
||||
expect(looksLikeDroppedPath('/model sonnet')).toBe(false)
|
||||
expect(looksLikeDroppedPath('/api')).toBe(false)
|
||||
})
|
||||
|
||||
it('accepts absolute paths with directory separators or extensions', () => {
|
||||
expect(looksLikeDroppedPath('/usr/bin/test')).toBe(true)
|
||||
expect(looksLikeDroppedPath('/tmp/file.txt')).toBe(true)
|
||||
expect(looksLikeDroppedPath('/etc/hosts')).toBe(true) // has second /
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue