fix(tui): honor file reference boundaries
This commit is contained in:
@@ -105,6 +105,24 @@ describe('WorkspaceFileSearch', () => {
|
||||
])
|
||||
expect(await files.list('~/.dsh-file-autocomplete-missing/', signal)).toEqual([])
|
||||
expect(await files.list('../', signal)).toEqual([])
|
||||
expect(await files.list('README.md/', signal)).toEqual([])
|
||||
})
|
||||
|
||||
it('does not traverse directory symlinks during direct completion', async () => {
|
||||
const root = await workspace()
|
||||
const outside = await mkdtemp(join(tmpdir(), 'dsh-file-autocomplete-outside-'))
|
||||
roots.push(outside)
|
||||
await writeFile(join(outside, 'outside-secret.txt'), 'secret')
|
||||
await symlink(
|
||||
outside,
|
||||
join(root, 'escape'),
|
||||
process.platform === 'win32' ? 'junction' : 'dir',
|
||||
)
|
||||
const files = search(root)
|
||||
const signal = new AbortController().signal
|
||||
|
||||
expect(await files.list('escape/', signal)).toEqual([])
|
||||
expect(await files.list('escape/outside', signal)).toEqual([])
|
||||
})
|
||||
|
||||
it('ranks basename and subsequence fuzzy matches across the bounded workspace index', async () => {
|
||||
|
||||
@@ -1153,22 +1153,34 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
})
|
||||
|
||||
it('shows file-reference guidance only while read is visible to the agent', async () => {
|
||||
const tools: Record<string, ToolDefinition> = {}
|
||||
const result = await setup({ tools })
|
||||
const read: ToolDefinition = {
|
||||
name: 'read',
|
||||
description: 'Read a file.',
|
||||
parameters: {},
|
||||
execute: () => Promise.resolve([]),
|
||||
}
|
||||
let visibility: 'none' | 'global' | 'agent' = 'none'
|
||||
const result = await setup({
|
||||
async configureContext(ctx) {
|
||||
ctx.provide('tools', {
|
||||
get(name: string, scope?: Agent) {
|
||||
if (name !== 'read' || visibility === 'none') return undefined
|
||||
return (scope === undefined) === (visibility === 'global') ? read : undefined
|
||||
},
|
||||
} as never)
|
||||
},
|
||||
})
|
||||
const fileReferenceText = async (): Promise<string | undefined> => {
|
||||
const assembly = await result.ctx.systemPrompt.assemble(assembleContextFor(result.agent))
|
||||
return assembly.sections.find(section => section.name === 'ui:tui-file-reference')?.text
|
||||
}
|
||||
try {
|
||||
expect(await fileReferenceText()).toBe('')
|
||||
tools.read = {
|
||||
name: 'read',
|
||||
description: 'Read a file.',
|
||||
parameters: {},
|
||||
execute: () => Promise.resolve([]),
|
||||
}
|
||||
visibility = 'global'
|
||||
expect(await fileReferenceText()).toBe('')
|
||||
visibility = 'agent'
|
||||
expect(await fileReferenceText()).toBe(FILE_REFERENCE_PROMPT)
|
||||
delete tools.read
|
||||
visibility = 'none'
|
||||
expect(await fileReferenceText()).toBe('')
|
||||
} finally {
|
||||
await dispose(result)
|
||||
|
||||
Reference in New Issue
Block a user