cowrite-dev / test /default-agent.js
Agent Manager
Close stdin for managed OpenCode runs
1126bdd
Raw
History Blame Contribute Delete
4.2 kB
import assert from 'node:assert/strict'
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
const data = fs.mkdtempSync(path.join(os.tmpdir(), 'cowrite-default-agent-'))
process.env.DATA_DIR = data
const { defaultAgentHandle, ensureDefaultAgent, execFileWithClosedStdin, openCodeArgs, openCodeEnv, openCodeProcessSummary, parseAgentAnswer, prepareOpenCode, safeError } = await import('../server/default-agent.js')
const agents = {
'alice-cowrite': { owner: 'someone-else' },
}
const handle = defaultAgentHandle('Alice', agents)
assert.match(handle, /^[a-z0-9][a-z0-9_.-]{1,38}$/)
assert.notEqual(handle, 'alice-cowrite')
assert.equal(defaultAgentHandle('Bob', {}), 'bob-cowrite')
const managed = ensureDefaultAgent('Alice')
const stored = JSON.parse(fs.readFileSync(path.join(data, 'agents.json'), 'utf8'))[managed]
assert.equal(stored.owner, 'Alice')
assert.equal(stored.managed, 'cowrite')
assert.equal(stored.shared, false)
assert.equal(stored.keyHash, undefined)
const { pollMentions, snapshotMentions } = await import('../server/collab.js')
assert.match(snapshotMentions('Alice').error || '', /no agent handles/, 'external owner-token polls cannot claim built-in work')
assert.deepEqual(await pollMentions('Alice', 0, managed, { includeManaged: true }), { mentions: [] })
const prepared = prepareOpenCode('Alice')
const { configPath } = prepared
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'))
assert.equal(config.autoupdate, false)
assert.equal(config.permission['*'], 'deny')
assert.equal(config.permission.websearch, 'allow')
assert.equal(config.permission.webfetch, 'deny')
assert.equal(config.provider['cowrite-hf'].options.apiKey, '{env:HF_OAUTH_TOKEN}', 'config references the in-memory token by environment name')
const isolatedEnv = openCodeEnv(prepared, 'test-oauth-token')
assert.equal(isolatedEnv.OPENCODE_DISABLE_MODELS_FETCH, 'true')
assert.equal(isolatedEnv.OPENCODE_FAST_BOOT, 'true')
assert.equal(isolatedEnv.OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER, 'true')
assert.equal(isolatedEnv.OPENCODE_DISABLE_DEFAULT_PLUGINS, 'true')
assert.equal(isolatedEnv.OPENCODE_DISABLE_PROJECT_CONFIG, 'true')
assert.equal(isolatedEnv.HF_OAUTH_TOKEN, 'test-oauth-token')
const commandArgs = openCodeArgs('/isolated/workspace', 'private prompt')
assert.deepEqual(commandArgs.slice(0, 4), ['run', '--pure', '--auto', '--format'])
assert.equal(commandArgs[commandArgs.indexOf('--title') + 1], 'Cowrite task')
assert.equal(commandArgs.at(-1), 'private prompt')
const stdinProbe = await execFileWithClosedStdin(process.execPath, [
'-e',
'process.stdin.resume(); process.stdin.on("end", () => process.stdout.write("closed"))',
], { timeout: 2_000 })
assert.equal(stdinProbe.stdout, 'closed', 'managed subprocess receives EOF after the command-line prompt')
const secret = 'hf_oauth_secret-value_with-more'
assert.equal(safeError(new Error(`provider rejected ${secret}`), [secret]).includes('secret-value'), false)
assert.equal(safeError(new Error('provider rejected hf_oauth_tail-with_more')).includes('tail'), false)
const processSummary = openCodeProcessSummary({
killed: true,
signal: 'SIGTERM',
stdout: [
JSON.stringify({ type: 'step_start' }),
JSON.stringify({ type: 'text', part: { text: 'private document output' } }),
JSON.stringify({ type: 'error', error: { data: { statusCode: 429, message: `retry ${secret}` } } }),
].join('\n'),
stderr: 'message="creating instance"\nmessage="llm runtime selected" private stderr',
}, [secret])
assert.match(processSummary, /timeout_or_kill/)
assert.match(processSummary, /events=step_start:1,text:1,error:1/)
assert.match(processSummary, /provider=429 retry \[redacted\]/)
assert.match(processSummary, /stages=instance,llm_selected/)
assert.doesNotMatch(processSummary, /private document output|private stderr|secret-value/)
assert.deepEqual(parseAgentAnswer('```json\n{"reply":"Done","suggestions":[],"dismiss":false}\n```'), {
reply: 'Done',
suggestions: [],
dismiss: false,
})
assert.throws(() => parseAgentAnswer('not json'), /JSON object/)
fs.rmSync(data, { recursive: true, force: true })
console.log('✓ default agent handle + structured answer parsing')