119 lines
3.0 KiB
TypeScript
119 lines
3.0 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
boundedToolDetail,
|
|
safeToolArgumentSummary,
|
|
safeToolErrorDetail
|
|
} from './approval-summary'
|
|
|
|
describe('safeToolArgumentSummary', () => {
|
|
it('redacts nested sensitive fields', () => {
|
|
expect(
|
|
safeToolArgumentSummary({
|
|
command: 'deploy',
|
|
options: {
|
|
apiKey: 'secret-value',
|
|
nested: { authorization: 'Bearer token-value' }
|
|
}
|
|
})
|
|
).toBe(
|
|
'{"command":"deploy","options":{"apiKey":"[REDACTED]","nested":{"authorization":"[REDACTED]"}}}'
|
|
)
|
|
})
|
|
|
|
it('redacts secrets in tool previews and bounds output', () => {
|
|
expect(
|
|
safeToolArgumentSummary(
|
|
{},
|
|
[{ content: 'curl -H "Authorization: Bearer secret-token"' }],
|
|
80
|
|
)
|
|
).not.toContain('secret-token')
|
|
})
|
|
})
|
|
|
|
describe('boundedToolDetail', () => {
|
|
it('preserves conversation details verbatim while bounding output', () => {
|
|
expect(
|
|
boundedToolDetail(
|
|
{
|
|
command: 'npm test',
|
|
token: 'secret-token',
|
|
output: 'Authorization: Bearer inline-secret'
|
|
},
|
|
1_000
|
|
)
|
|
).toBe(
|
|
'{\n "command": "npm test",\n "token": "secret-token",\n "output": "Authorization: Bearer inline-secret"\n}'
|
|
)
|
|
expect(
|
|
boundedToolDetail(' exact output\r\n', 1_000)
|
|
).toBe(' exact output\r\n')
|
|
expect(boundedToolDetail('x'.repeat(100), 20)).toHaveLength(20)
|
|
})
|
|
})
|
|
|
|
describe('safeToolErrorDetail', () => {
|
|
it('extracts nested runtime errors without rewriting their contents', () => {
|
|
expect(
|
|
safeToolErrorDetail([
|
|
{
|
|
content:
|
|
'exit code 1\nAuthorization: Bearer secret-token'
|
|
}
|
|
])
|
|
).toBe('exit code 1\nAuthorization: Bearer secret-token')
|
|
expect(
|
|
safeToolErrorDetail({
|
|
message:
|
|
'{"token":"json-secret","authorization":"Basic abc123"}'
|
|
})
|
|
).toBe(
|
|
'{"token":"json-secret","authorization":"Basic abc123"}'
|
|
)
|
|
})
|
|
|
|
it('bounds output and ignores unrelated provider payload fields', () => {
|
|
expect(
|
|
safeToolErrorDetail(
|
|
{
|
|
content: 'parser failure '.repeat(20),
|
|
privateDocument: 'must not be returned'
|
|
},
|
|
40
|
|
)
|
|
).toHaveLength(40)
|
|
expect(
|
|
safeToolErrorDetail({
|
|
privateDocument: 'must not be returned'
|
|
})
|
|
).toBeUndefined()
|
|
})
|
|
|
|
it('includes nested fetch causes and network diagnostics', () => {
|
|
const cause = Object.assign(
|
|
new Error('connect ECONNREFUSED 127.0.0.1:11434'),
|
|
{
|
|
code: 'ECONNREFUSED',
|
|
errno: -4078,
|
|
syscall: 'connect',
|
|
address: '127.0.0.1',
|
|
port: 11434
|
|
}
|
|
)
|
|
const error = new TypeError('fetch failed', { cause })
|
|
|
|
expect(safeToolErrorDetail(error)).toBe(
|
|
[
|
|
'fetch failed',
|
|
'cause:',
|
|
'connect ECONNREFUSED 127.0.0.1:11434',
|
|
'code: ECONNREFUSED',
|
|
'errno: -4078',
|
|
'syscall: connect',
|
|
'address: 127.0.0.1',
|
|
'port: 11434'
|
|
].join('\n')
|
|
)
|
|
})
|
|
})
|