import { describe, expect, it } from 'bun:test'
import {
DEFAULT_CHANNEL_KEY,
DEFAULT_MAX_OUTPUT_TOKENS,
OGComputeBrain,
detectBlockedToolError,
looksLikeValidJsonString,
stripThinkBlocks,
} from './og-compute'
import type { BrainMessage } from './types'
const TEST_PK = '0x1111111111111111111111111111111111111111111111111111111111111111'
const NO_PREFIX = {
systemPrompt: 'test',
memoryIndexText: null,
identityText: null,
personaText: null,
skillIndexText: null,
toolGuidance: [],
appendText: null,
envText: null,
timestamp: null,
}
function makeBrain(opts: { history?: BrainMessage[] } = {}): OGComputeBrain {
return new OGComputeBrain({
privkeyHex: TEST_PK as `0x${string}`,
rpcUrl: 'https://does-not-matter',
providerAddress: '0x0000000000000000000000000000000000000000',
tools: [],
prefix: NO_PREFIX,
history: opts.history,
})
}
describe('detectBlockedToolError (qwen safety-filter recovery)', () => {
it('matches the canonical broker error string', () => {
const content =
'An error occurred while generating a tool call: Unauthorized: browser is a blocked tool.'
expect(detectBlockedToolError(content)).toBe('browser')
})
it('matches without the leading prefix', () => {
expect(detectBlockedToolError('Unauthorized: shell is a blocked tool.')).toBe('shell')
})
it('returns null for normal assistant content', () => {
expect(detectBlockedToolError('The first result is "Wikipedia: HTTP".')).toBe(null)
expect(detectBlockedToolError('')).toBe(null)
expect(detectBlockedToolError('I called browser.snapshot and got the page.')).toBe(null)
})
it('returns null for similar-looking but non-matching strings', () => {
expect(detectBlockedToolError('Unauthorized request')).toBe(null)
expect(detectBlockedToolError('blocked tool: browser')).toBe(null)
})
})
describe('OGComputeBrain abort signal', () => {
it('rejects with AbortError when signal is aborted before infer starts', async () => {
const brain = makeBrain()
// Manually flag as initialized so init() is skipped (we want to hit the
// abort check, not the broker init network call).
;(brain as unknown as { broker: unknown }).broker = {}
const ctrl = new AbortController()
ctrl.abort()
await expect(
brain.infer({
event: {
id: 'test',
source: 'stdin',
payload: { label: 'user-message', data: 'hello' },
ts: Date.now(),
},
signal: ctrl.signal,
}),
).rejects.toMatchObject({ name: 'AbortError' })
})
})
describe('OGComputeBrain channel-keyed history', () => {
it('seeds default channel from constructor opts.history', () => {
const seed: BrainMessage[] = [
{ role: 'user', content: 'old1' },
{ role: 'assistant', content: 'old2' },
]
const brain = makeBrain({ history: seed })
expect(brain.getChannelHistory(DEFAULT_CHANNEL_KEY)).toEqual(seed)
})
it('returns empty for unseen channels', () => {
const brain = makeBrain()
expect(brain.getChannelHistory('tui:stdin')).toEqual([])
expect(brain.getChannelHistory('agent:specter:tg:dm:42')).toEqual([])
})
it('setChannelHistory partitions per key', () => {
const brain = makeBrain()
brain.setChannelHistory('tui:stdin', [{ role: 'user', content: 'A' }])
brain.setChannelHistory('agent:specter:tg:dm:42', [{ role: 'user', content: 'B' }])
expect(brain.getChannelHistory('tui:stdin')).toEqual([{ role: 'user', content: 'A' }])
expect(brain.getChannelHistory('agent:specter:tg:dm:42')).toEqual([
{ role: 'user', content: 'B' },
])
})
it('clearChannel only clears the named channel', async () => {
const brain = makeBrain()
brain.setChannelHistory('tui:stdin', [{ role: 'user', content: 'A' }])
brain.setChannelHistory('tg', [{ role: 'user', content: 'B' }])
await brain.clearChannel('tui:stdin')
expect(brain.getChannelHistory('tui:stdin')).toEqual([])
expect(brain.getChannelHistory('tg')).toEqual([{ role: 'user', content: 'B' }])
})
it('listChannels enumerates non-empty channels', () => {
const brain = makeBrain()
expect(brain.listChannels()).toEqual([])
brain.setChannelHistory('tui:stdin', [{ role: 'user', content: 'A' }])
brain.setChannelHistory('tg', [{ role: 'user', content: 'B' }])
expect(brain.listChannels().sort()).toEqual(['tg', 'tui:stdin'])
})
it('getChannelHistory returns a defensive copy', () => {
const brain = makeBrain()
brain.setChannelHistory('tui:stdin', [{ role: 'user', content: 'A' }])
const snapshot = brain.getChannelHistory('tui:stdin') as BrainMessage[]
snapshot.push({ role: 'user', content: 'mutated' })
expect(brain.getChannelHistory('tui:stdin').length).toBe(1)
})
})
describe('OGComputeBrain config defaults', () => {
it('exposes DEFAULT_MAX_OUTPUT_TOKENS at 4096', () => {
expect(DEFAULT_MAX_OUTPUT_TOKENS).toBe(4096)
})
it('exposes DEFAULT_CHANNEL_KEY as "default"', () => {
expect(DEFAULT_CHANNEL_KEY).toBe('default')
})
})
describe('looksLikeValidJsonString (malformed tool_call args guard)', () => {
it('accepts valid JSON object string', () => {
expect(looksLikeValidJsonString('{"query":"x"}')).toBe(true)
})
it('accepts valid JSON array string', () => {
expect(looksLikeValidJsonString('[1,2,3]')).toBe(true)
})
it('accepts empty string (no args)', () => {
expect(looksLikeValidJsonString('')).toBe(true)
})
it('rejects truncated object (the May 6 enigma case)', () => {
expect(looksLikeValidJsonString('{"query": "browser navigate"')).toBe(false)
})
it('rejects truncated array', () => {
expect(looksLikeValidJsonString('[1,2,')).toBe(false)
})
it('rejects unbalanced braces', () => {
expect(looksLikeValidJsonString('{"a":{"b":1}')).toBe(false)
})
})
describe('stripThinkBlocks (Qwen reasoning_content fallback)', () => {
it('strips a single think block', () => {
expect(stripThinkBlocks('thinking out loudactual answer')).toBe('actual answer')
})
it('strips multiple think blocks', () => {
expect(stripThinkBlocks('axby')).toBe('xy')
})
it('strips multiline think blocks', () => {
expect(stripThinkBlocks('\nline1\nline2\n\nanswer here')).toBe('answer here')
})
it('returns plain text untouched', () => {
expect(stripThinkBlocks('plain text answer')).toBe('plain text answer')
})
it('handles empty input', () => {
expect(stripThinkBlocks('')).toBe('')
})
it('strips even when nothing follows the think block', () => {
expect(stripThinkBlocks('only thinking, no answer')).toBe('')
})
})