Desktop persisted a large paste under Electron's userData dir and attached it as `@file:<abs path>`; the tui_gateway prompt path expands that reference with `allowed_root=cwd`, so `_resolve_path` refused it with "path is outside the allowed workspace" whenever the chat's cwd was not an ancestor of the paste dir (always on Linux/macOS, and on Windows for any project cwd). Electron now writes pastes under `<HERMES_HOME>/composer-pastes`, and `agent/context_references.py::_resolve_path` admits exactly that anchored directory (active profile home and global root, via file_safety._hermes_dirs) as the one root besides `allowed_root`. A sibling directory that merely contains the substring stays refused; the credential deny-list still runs on the admitted path. Supersedes the substring whitelist proposed in #117150. Fixes #117149
28 lines
859 B
TypeScript
28 lines
859 B
TypeScript
import fs from 'node:fs'
|
|
import os from 'node:os'
|
|
import path from 'node:path'
|
|
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
|
|
import { COMPOSER_PASTES_DIRNAME, writeComposerPaste } from './composer-paste'
|
|
|
|
const scratch: string[] = []
|
|
|
|
afterEach(() => {
|
|
for (const dir of scratch.splice(0)) {
|
|
fs.rmSync(dir, { force: true, recursive: true })
|
|
}
|
|
})
|
|
|
|
describe('writeComposerPaste', () => {
|
|
it('lands the paste directly under <HERMES_HOME>/composer-pastes so the backend admits it', async () => {
|
|
const hermesHome = fs.mkdtempSync(path.join(os.tmpdir(), 'hermes-home-'))
|
|
scratch.push(hermesHome)
|
|
|
|
const filePath = await writeComposerPaste(hermesHome, 'pasted body')
|
|
|
|
expect(path.dirname(filePath)).toBe(path.join(hermesHome, COMPOSER_PASTES_DIRNAME))
|
|
expect(fs.readFileSync(filePath, 'utf8')).toBe('pasted body')
|
|
})
|
|
})
|