v1.1.0: native diff card client, 200-line paging for read/grep/glob, guard rule against shell edits/reads/searches
This commit is contained in:
1 parent
71953ffb8f
commit
0dae0ee53d
5 files changed
+364
-22
No files matched your search
@@ -152,3 +152,45 @@ test('model switch re-registers the edit tool in the agent scope', async () => {
|
||||
assert.ok(h.ctx.tools.get('edit', agent).parameters.properties.old_string)
|
||||
h.cleanup()
|
||||
})
|
||||
|
||||
test('guard denies shell edits/reads/searches and non-hashline write tools via tools/pre-execute', async () => {
|
||||
const { h } = await setup()
|
||||
const gate = async (name, args) => {
|
||||
const cbs = [...(h.listeners.get('tools/pre-execute') ?? [])]
|
||||
const exec = { name, arguments: args, agent: { session: { header: { cwd: h.dir } } }, signal: new AbortController().signal }
|
||||
const next = () => (cbs.shift() ?? (async () => ({ kind: 'allow' })))(exec, next)
|
||||
return next()
|
||||
}
|
||||
assert.equal((await gate('bash', { command: 'sed -i s/a/b/ f.txt' })).kind, 'deny')
|
||||
assert.equal((await gate('bash', { command: 'grep -rn foo .' })).kind, 'deny')
|
||||
assert.equal((await gate('bash', { command: 'cat README.md' })).kind, 'deny')
|
||||
h.write('exists.txt', 'old\n')
|
||||
const d = await gate('write', { file_path: 'exists.txt', content: 'y' })
|
||||
assert.equal(d.kind, 'deny')
|
||||
assert.match(d.reason, /only create new files/)
|
||||
assert.equal((await gate('write', { file_path: 'brand-new.txt', content: 'y' })).kind, 'allow')
|
||||
assert.equal((await gate('str_replace_editor', { command: 'create', path: 'z' })).kind, 'deny')
|
||||
// A stat failure must not fail open.
|
||||
const realStat = h.ctx.fs.stat
|
||||
h.ctx.fs.stat = async () => { throw Object.assign(new Error('permission denied'), { code: 'EACCES' }) }
|
||||
const e = await gate('write', { file_path: 'locked.txt', content: 'y' })
|
||||
h.ctx.fs.stat = realStat
|
||||
assert.equal(e.kind, 'deny')
|
||||
assert.match(e.reason, /could not check/)
|
||||
assert.equal((await gate('bash', { command: 'npm test 2>&1 | tail -5' })).kind, 'allow')
|
||||
assert.equal((await gate('edit', { input: '[a#0000]\nPUT 1.=1:\n+x' })).kind, 'allow')
|
||||
h.cleanup()
|
||||
})
|
||||
|
||||
test('grep pages at pageLines with an offset cursor', async () => {
|
||||
const { h, agent } = await setup({ pageLines: 3 })
|
||||
h.write('many.txt', Array.from({ length: 8 }, (_, i) => `hit ${i}`).join('\n') + '\n')
|
||||
const p1 = await h.call(agent, 'grep', { pattern: 'hit' })
|
||||
assert.match(p1.text, /8 matches in 1 file — showing 1-3/)
|
||||
assert.match(p1.text, /call grep again with offset=3/)
|
||||
const p2 = await h.call(agent, 'grep', { pattern: 'hit', offset: 6 })
|
||||
assert.match(p2.text, /showing 7-8/)
|
||||
assert.match(p2.text, /^8:hit 7$/m)
|
||||
assert.doesNotMatch(p2.text, /offset=/)
|
||||
h.cleanup()
|
||||
})
|
||||
Reference in new issue
Block a user