Files
bare-operating-system/packages/bare-os-coreutils/test/agent-think-panel.test.mjs
T
2026-08-18 18:11:34 -04:00

153 lines
4.3 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
import vm from 'node:vm'
const dir = dirname(fileURLToPath(import.meta.url))
/**
* @param {string} rel
* @param {string[]} names
*/
function loadFns(rel, names) {
const src = readFileSync(join(dir, rel), 'utf8')
const sandbox = {
console,
bareEditSgr: (cls, on) => (on ? '\x1b[2m' : ''),
EDIT_ANSI_RESET: '\x1b[0m',
bareEditChunkBytes: (chunk) => {
if (typeof chunk === 'string') {
const out = []
for (let i = 0; i < chunk.length; i++) out.push(chunk.charCodeAt(i) & 0xff)
return out
}
return []
},
bareEditTryConsumeKey: () => null
}
vm.createContext(sandbox)
vm.runInContext(src, sandbox)
/** @type {Record<string, Function>} */
const api = {}
for (const n of names) {
assert.equal(typeof sandbox[n], 'function', 'missing ' + n)
api[n] = sandbox[n]
}
return api
}
test('markdown renders headings lists and bold', () => {
const api = loadFns('../lib/agent/agent-markdown.js', ['bareAgentRenderMarkdown'])
const out = api.bareAgentRenderMarkdown(
'# Title\n\nI use **bold** and `code`.\n\n1. One\n2. Two\n\n- Alpha\n- Beta\n',
{ useColor: false, width: 72 }
)
assert.match(out, /Title/)
assert.match(out, /bold/)
assert.match(out, /code/)
assert.match(out, /1\. One/)
assert.match(out, /• Alpha/)
})
test('markdown fences keep code body', () => {
const api = loadFns('../lib/agent/agent-markdown.js', ['bareAgentRenderMarkdown'])
const out = api.bareAgentRenderMarkdown('```js\nconst x = 1\n```\n', {
useColor: false,
width: 72
})
assert.match(out, /const x = 1/)
assert.match(out, /js/)
})
test('think panel scrollbar and scroll keys', () => {
const api = loadFns('../lib/agent/agent-think-panel.js', [
'bareAgentCreateThinkPanel',
'bareAgentThinkScrollbar'
])
const sb = api.bareAgentThinkScrollbar(4, 20, 0, false)
assert.equal(sb.length, 4)
assert.ok(sb.some((c) => c === '#'))
/** @type {string[]} */
const writes = []
const panel = api.bareAgentCreateThinkPanel(
{ env: { COLUMNS: '72', BARE_OS_AGENT_ASCII: '1' } },
{ isTTY: true, columns: 72, write: () => true },
{
useColor: false,
bodyLines: 4,
write: (_c, _o, s) => writes.push(s)
}
)
for (let i = 0; i < 20; i++) {
panel.append('Line number ' + i + ' about tools and skills.\n')
}
assert.ok(writes.length >= 1)
const before = writes.length
panel.scrollUp(3)
assert.ok(writes.length > before)
panel.handleKey({ type: 'nav', key: 'pageup' })
panel.seal()
assert.ok(panel.hasContent())
panel.setStatus('answering…')
panel.clearStatus()
})
test('term cols use full width without 120 cap', () => {
const api = loadFns('../lib/agent/agent-think-panel.js', [
'bareAgentResolveTermCols'
])
const w = api.bareAgentResolveTermCols(
{ env: { COLUMNS: '80' } },
{ columns: 200 }
)
assert.equal(w, 200)
const w2 = api.bareAgentResolveTermCols({ env: { COLUMNS: '160' } }, {})
assert.equal(w2, 160)
})
test('empty think panel never draws', () => {
const api = loadFns('../lib/agent/agent-think-panel.js', [
'bareAgentCreateThinkPanel'
])
/** @type {string[]} */
const writes = []
const panel = api.bareAgentCreateThinkPanel(
{ env: { COLUMNS: '100' } },
{ isTTY: true, columns: 100, write: () => true },
{
useColor: false,
bodyLines: 4,
write: (_c, _o, s) => writes.push(s)
}
)
panel.append('\n\n \n')
panel.seal()
panel.setStatus('should not show')
assert.equal(writes.length, 0)
assert.equal(panel.hasContent(), false)
panel.append('real thought')
assert.ok(writes.length >= 1)
assert.ok(panel.hasContent())
})
test('think tag splitter still works', () => {
const api = loadFns('../lib/agent/agent-think-panel.js', [
'bareAgentCreateThinkTagSplitter'
])
/** @type {string[]} */
const think = []
/** @type {string[]} */
const content = []
const split = api.bareAgentCreateThinkTagSplitter({
onThink: (s) => think.push(s),
onContent: (s) => content.push(s)
})
split.push('<think>plan</think>\nAnswer **here**')
split.flush()
assert.equal(think.join(''), 'plan')
assert.equal(content.join(''), '\nAnswer **here**')
})