Files
bare-operating-system/packages/bare-os-coreutils/test/agent-workspace.test.mjs
T

229 lines
8.2 KiB
JavaScript

/**
* Agent workspace loader (VM, same preamble order as /bin/agent).
*/
import test from 'brittle'
import { readFileSync } from 'node:fs'
import vm from 'node:vm'
const CODE = readFileSync(
new URL('../lib/agent-workspace.js', import.meta.url),
'utf8'
)
/** @returns {Record<string, unknown>} */
function load(extra = {}) {
const sandbox = {
TextDecoder,
TextEncoder,
Uint8Array,
console,
...extra
}
vm.createContext(sandbox)
vm.runInContext(CODE, sandbox, { filename: 'agent-workspace.js' })
return sandbox
}
test('bareAgentLoadWorkspacePrompt concatenates files', async (t) => {
const files = new Map()
files.set('/home/x/.agent/workspace/SOUL.md', '# Hi')
files.set('/home/x/.agent/workspace/AGENTS.md', '# Rules')
for (const n of [
'IDENTITY.md',
'USER.md',
'TOOLS.md',
'MEMORY.md',
'BOOTSTRAP.md',
'HEARTBEAT.md',
'PROMPT.md'
])
files.set('/home/x/.agent/workspace/' + n, '# ' + n)
const vfs = {
readFile: async (p) => {
const u = files.get(p)
if (!u) throw new Error('enoent')
return new TextEncoder().encode(u)
}
}
const s = load()
const loadFn = /** @type {(ctx: object, paths: object, cap?: number) => Promise<string>} */ (
s.bareAgentLoadWorkspacePrompt
)
const block = await loadFn(
{ vfs, b4a: null },
{ workspace: '/home/x/.agent/workspace', workspaceMemory: '/home/x/.agent/workspace/memory' },
50000
)
t.ok(block.includes('=== SOUL.md ==='))
t.ok(block.includes('# Hi'))
t.ok(block.includes('=== AGENTS.md ==='))
})
test('bareAgentEnsureWorkspace seeds from share', async (t) => {
const written = []
const files = new Map()
const set = (p, txt) => files.set(p, txt)
set('/share/agent-workspace/SOUL.md', '# Seeded soul')
set('/share/agent-workspace/AGENTS.md', '# A')
set('/share/agent-workspace/IDENTITY.md', '# I')
set('/share/agent-workspace/USER.md', '# U')
set('/share/agent-workspace/TOOLS.md', '# T')
set('/share/agent-workspace/MEMORY.md', '# M')
set('/share/agent-workspace/BOOTSTRAP.md', '# B')
set('/share/agent-workspace/HEARTBEAT.md', '# H')
set('/share/agent-workspace/PROMPT.md', '# P')
set('/share/agent-workspace/memory/.gitkeep', '')
set('/share/agent-workspace/loader.stub.js', '// l')
set('/share/agent-workspace/index.stub.js', '// i')
set('/share/agent-workspace/skill-loader.stub.js', '// sl')
set('/share/agent-workspace/README-agent.md', '# R')
const vfs = {
async mkdir(_p, _o) {},
async readFile(p) {
if (files.has(p)) return new TextEncoder().encode(files.get(p))
throw new Error('enoent')
},
async writeFile(p, buf) {
const txt =
buf instanceof Uint8Array ? new TextDecoder().decode(buf) : String(buf)
written.push([p, txt])
files.set(p, txt)
}
}
const s = load()
const ensure = /** @type {(ctx: object, paths: object) => Promise<void>} */ (
s.bareAgentEnsureWorkspace
)
await ensure(
{ vfs, b4a: null },
{
dir: '/home/x/.agent',
workspace: '/home/x/.agent/workspace',
workspaceMemory: '/home/x/.agent/workspace/memory',
workspaceSkills: '/home/x/.agent/workspace/skills'
}
)
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/SOUL.md'))
const soul = written.find(([p]) => p === '/home/x/.agent/workspace/SOUL.md')
t.ok(soul && soul[1].includes('Seeded soul'))
t.ok(written.some(([p]) => p === '/home/x/.agent/skill-loader.js'))
})
test('bareAgentEnsureSkillTemplates copies skill seeds when missing for xai provider', async (t) => {
const written = []
const files = new Map()
const set = (p, txt) => files.set(p, txt)
set('/share/agent-workspace/skills/.gitkeep', '')
set('/share/agent-workspace/skills/p2p-os-status/SKILL.md', '# Skill')
set('/share/agent-workspace/skills/bare-os-kernel-proc/SKILL.md', '# Proc skill')
set('/share/agent-workspace/skills/bare-os-super-developer/SKILL.md', '# Dev skill')
set('/share/agent-workspace/skills/agent-ops/SKILL.md', '# Ops skill')
set('/share/agent-workspace/skills/xai-compat/SKILL.md', '# xAI skill')
set('/share/agent-workspace/skills/holesail/SKILL.md', '# Holesail skill')
set('/share/agent-workspace/skills/hdms/SKILL.md', '# Hdms skill')
set('/share/agent-workspace/skill-loader.stub.js', '// stub')
const vfs = {
async mkdir(_p, _o) {},
async readFile(p) {
if (files.has(p)) return new TextEncoder().encode(files.get(p))
throw new Error('enoent')
},
async writeFile(p, buf) {
const txt =
buf instanceof Uint8Array ? new TextDecoder().decode(buf) : String(buf)
written.push([p, txt])
files.set(p, txt)
}
}
const s = load()
const fn = /** @type {(ctx: object, paths: object) => Promise<void>} */ (
s.bareAgentEnsureSkillTemplates
)
await fn(
{ vfs, b4a: null },
{
dir: '/home/x/.agent',
workspace: '/home/x/.agent/workspace',
workspaceSkills: '/home/x/.agent/workspace/skills'
},
{ provider: 'xai' }
)
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/p2p-os-status/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/bare-os-kernel-proc/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/bare-os-super-developer/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/agent-ops/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/xai-compat/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/holesail/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/hdms/SKILL.md'))
t.ok(written.some(([p]) => p === '/home/x/.agent/skill-loader.js'))
})
test('bareAgentEnsureSkillTemplates skips xai skill for non-xai provider', async (t) => {
const written = []
const files = new Map()
const set = (p, txt) => files.set(p, txt)
set('/share/agent-workspace/skills/.gitkeep', '')
set('/share/agent-workspace/skills/p2p-os-status/SKILL.md', '# Skill')
set('/share/agent-workspace/skills/bare-os-kernel-proc/SKILL.md', '# Proc skill')
set('/share/agent-workspace/skills/bare-os-super-developer/SKILL.md', '# Dev skill')
set('/share/agent-workspace/skills/agent-ops/SKILL.md', '# Ops skill')
set('/share/agent-workspace/skills/xai-compat/SKILL.md', '# xAI skill')
set('/share/agent-workspace/skills/holesail/SKILL.md', '# Holesail skill')
set('/share/agent-workspace/skills/hdms/SKILL.md', '# Hdms skill')
set('/share/agent-workspace/skill-loader.stub.js', '// stub')
const vfs = {
async mkdir(_p, _o) {},
async readFile(p) {
if (files.has(p)) return new TextEncoder().encode(files.get(p))
throw new Error('enoent')
},
async writeFile(p, buf) {
const txt =
buf instanceof Uint8Array ? new TextDecoder().decode(buf) : String(buf)
written.push([p, txt])
files.set(p, txt)
}
}
const s = load()
const fn = /** @type {(ctx: object, paths: object, cfg?: object) => Promise<void>} */ (
s.bareAgentEnsureSkillTemplates
)
await fn(
{ vfs, b4a: null },
{
dir: '/home/x/.agent',
workspace: '/home/x/.agent/workspace',
workspaceSkills: '/home/x/.agent/workspace/skills'
},
{ provider: 'groq' }
)
t.ok(written.some(([p]) => p === '/home/x/.agent/workspace/skills/p2p-os-status/SKILL.md'))
t.ok(!written.some(([p]) => p === '/home/x/.agent/workspace/skills/xai-compat/SKILL.md'))
})
test('bareAgentSyncWorkspaceFromConfig writes IDENTITY and USER from config', async (t) => {
const written = []
const vfs = {
async mkdir(_p, _o) {},
async writeFile(p, buf) {
const txt =
buf instanceof Uint8Array ? new TextDecoder().decode(buf) : String(buf)
written.push([p, txt])
}
}
const s = load()
const sync = /** @type {(ctx: object, paths: object, cfg: object) => Promise<void>} */ (
s.bareAgentSyncWorkspaceFromConfig
)
await sync(
{ vfs, b4a: null },
{ workspace: '/home/x/.agent/workspace' },
{ owner_name: 'Raven', agent_label: 'Bear' }
)
const id = written.find(([p]) => p === '/home/x/.agent/workspace/IDENTITY.md')
t.ok(id && id[1].includes('**Name:** Bear'))
t.ok(id && id[1].includes('Raven'))
const user = written.find(([p]) => p === '/home/x/.agent/workspace/USER.md')
t.ok(user && user[1].includes('Raven'))
})