96 lines
3.8 KiB
JavaScript
96 lines
3.8 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { createRequire } from 'node:module';
|
|
import { VOICE_SYSTEM_PROMPT } from '../skills/voice-prompt.js';
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const compaction = require('../vendor/agent-harness/agent/compaction.js');
|
|
const prompts = require('../vendor/agent-harness/agent/prompts.js');
|
|
|
|
function hugeTools() {
|
|
return Array.from({ length: 24 }, (_, i) => ({
|
|
name: 'tool_' + i,
|
|
description: 'schema '.repeat(80),
|
|
parameters: { type: 'object', properties: { q: { type: 'string' } } },
|
|
}));
|
|
}
|
|
|
|
test('short voice chats do not compact just because tool schemas are large', () => {
|
|
const tools = hugeTools();
|
|
const hist = [
|
|
{ role: 'system', content: VOICE_SYSTEM_PROMPT },
|
|
{ role: 'assistant', content: 'Hello! How can I help you today?' },
|
|
{ role: 'user', content: 'Hi, please tell me about my computer.' },
|
|
];
|
|
assert.equal(compaction.shouldCompact(hist, tools, 8192), false);
|
|
const out = compaction.compact(hist, {
|
|
budgetTokens: compaction.historyBudget(8192, tools, 0),
|
|
tools,
|
|
voice: true,
|
|
});
|
|
assert.equal(out.length, hist.length);
|
|
assert.equal(out[2].content, hist[2].content);
|
|
assert.equal(JSON.stringify(out).includes('Earlier turns were compacted'), false);
|
|
});
|
|
|
|
test('heuristic compact does not double-count tools against the history budget', () => {
|
|
const tools = hugeTools();
|
|
const hist = [
|
|
{ role: 'system', content: 'You are Jarvis' },
|
|
{ role: 'assistant', content: 'Hello! How can I help you today?' },
|
|
{ role: 'user', content: 'Hi, please tell me about my computer.' },
|
|
{ role: 'assistant', content: 'Let me check that.' },
|
|
{ role: 'user', content: 'Please continue.' },
|
|
];
|
|
const budget = compaction.historyBudget(8192, tools, 0);
|
|
assert.ok(budget <= 240 || compaction.toolTokens(tools) > 1000);
|
|
const out = compaction.heuristicCompact(hist, { budgetTokens: budget, tools });
|
|
assert.ok(out.some((m) => String(m.content).includes('tell me about my computer')));
|
|
assert.equal(JSON.stringify(out).includes('Earlier turns were compacted'), false);
|
|
});
|
|
|
|
test('voice compaction does not auto-continue a new greeting', () => {
|
|
const cont = compaction.autoContinue([{ role: 'assistant', content: 'Hello!' }], { voice: true });
|
|
assert.equal(cont, null);
|
|
assert.match(compaction.compactReminder({ voice: true }), /Do not greet again/);
|
|
});
|
|
|
|
test('voice assemble inlines workspace identity files and skips a completed bootstrap', () => {
|
|
const sys = prompts.assemble({
|
|
personality: 'voice',
|
|
extra: VOICE_SYSTEM_PROMPT,
|
|
cwd: '/home/raven/.local/share/jarvis/workspace',
|
|
hostWorkspace: true,
|
|
fsRead: (_c, n) => {
|
|
if (n === 'SOUL.md') return '# SOUL.md: Jarvis\nYou are Jarvis on this desktop.';
|
|
if (n === 'AGENTS.md') return '# AGENTS.md\nFollow the workspace ritual.';
|
|
if (n === 'BOOTSTRAP.md') return '# completed';
|
|
return '';
|
|
},
|
|
});
|
|
assert.match(sys, /You are Jarvis/);
|
|
assert.match(sys, /SOUL\.md/);
|
|
assert.match(sys, /AGENTS\.md/);
|
|
assert.doesNotMatch(sys, /You are a local coding agent/);
|
|
assert.doesNotMatch(sys, /## BOOTSTRAP\.md/);
|
|
});
|
|
|
|
test('LLM compact skips a two-turn voice chat', async () => {
|
|
let called = false;
|
|
const hist = [
|
|
{ role: 'system', content: 'You are Jarvis' },
|
|
{ role: 'assistant', content: 'Hello! How can I help you today?' },
|
|
{ role: 'user', content: 'Hi, please tell me about my computer.' },
|
|
];
|
|
const out = await compaction.compactWithLlm(hist, {
|
|
voice: true,
|
|
complete: async () => {
|
|
called = true;
|
|
return { text: '1. Latest user request\n2. Facts\n3. Answered\n4. Follow-ups\n' };
|
|
},
|
|
});
|
|
assert.equal(called, false);
|
|
assert.equal(out.length, hist.length);
|
|
assert.equal(out[2].content, hist[2].content);
|
|
});
|