Updates
Rolling release / release (push) Successful in 7m29s

This commit is contained in:
2026-09-12 16:46:49 -04:00
parent 04a9306594
commit 4383763cb5
20 changed files with 490 additions and 26 deletions
+3
View File
@@ -19,7 +19,10 @@ test('workspace seed copies SOUL and bootstrap, then name writes IDENTITY.md', (
assert.doesNotMatch(readFileSync(path.join(dir, 'AGENTS.md'), 'utf8'), /Pip/);
applyAssistantName(dir, 'Ada');
assert.match(readFileSync(path.join(dir, 'IDENTITY.md'), 'utf8'), /\*\*Name:\*\* Ada/);
assert.match(readFileSync(path.join(dir, 'IDENTITY.md'), 'utf8'), /Ada lives on this Ubuntu/);
assert.match(readFileSync(path.join(dir, 'SOUL.md'), 'utf8'), /# SOUL\.md: Ada/);
assert.match(readFileSync(path.join(dir, 'SOUL.md'), 'utf8'), /You are \*\*Ada\*\*/);
assert.doesNotMatch(readFileSync(path.join(dir, 'SOUL.md'), 'utf8'), /You are \*\*Jarvis\*\*/);
const again = ensureAgentWorkspace({ name: 'Ada' });
assert.equal(again, dir);
assert.match(readFileSync(path.join(dir, 'IDENTITY.md'), 'utf8'), /\*\*Name:\*\* Ada/);
+30 -1
View File
@@ -1,7 +1,7 @@
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';
import { VOICE_SYSTEM_PROMPT, voiceSystemPrompt } from '../skills/voice-prompt.js';
const require = createRequire(import.meta.url);
const compaction = require('../vendor/agent-harness/agent/compaction.js');
@@ -64,6 +64,7 @@ test('voice assemble inlines workspace identity files and skips a completed boot
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 === 'PERSONA.md') return '# PERSONA.md\nBe a roast comedian.';
if (n === 'BOOTSTRAP.md') return '# completed';
return '';
},
@@ -71,10 +72,38 @@ test('voice assemble inlines workspace identity files and skips a completed boot
assert.match(sys, /You are Jarvis/);
assert.match(sys, /SOUL\.md/);
assert.match(sys, /AGENTS\.md/);
assert.doesNotMatch(sys, /## PERSONA\.md/);
assert.doesNotMatch(sys, /Be a roast comedian/);
assert.doesNotMatch(sys, /You are a local coding agent/);
assert.doesNotMatch(sys, /## BOOTSTRAP\.md/);
});
test('voice assemble keeps acting notes in the system prompt and skips SOUL identity files', () => {
const extra = voiceSystemPrompt('Tony', 'Jarvis, you are acting as Tony Hinchcliffe. Never call yourself Jarvis.');
const sys = prompts.assemble({
personality: 'voice',
extra,
cwd: '/home/raven/.local/share/jarvis/workspace',
hostWorkspace: true,
fsRead: (_c, n) => {
if (n === 'SOUL.md') return '# SOUL.md: Jarvis\nYou are **Jarvis**.';
if (n === 'IDENTITY.md') return '# IDENTITY.md\nJarvis lives here.';
if (n === 'PERSONA.md') return '# PERSONA.md\nDuplicate roast notes.';
if (n === 'AGENTS.md') return '# AGENTS.md\nFollow the workspace ritual.';
return '';
},
});
assert.match(sys, /Your name is Tony/);
assert.match(sys, /## Acting/);
assert.match(sys, /Tony Hinchcliffe/);
assert.match(sys, /AGENTS\.md/);
assert.doesNotMatch(sys, /## SOUL\.md/);
assert.doesNotMatch(sys, /## IDENTITY\.md/);
assert.doesNotMatch(sys, /## PERSONA\.md/);
assert.doesNotMatch(sys, /Duplicate roast notes/);
assert.doesNotMatch(sys, /You are \*\*Jarvis\*\*/);
});
test('LLM compact skips a two-turn voice chat', async () => {
let called = false;
const hist = [
+6
View File
@@ -40,6 +40,12 @@ test('typed questions barge in from SPEAKING', () => {
test('spoken replies use harness text and strip HUD sidecars', () => {
assert.equal(spokenReply({ ok: true, text: 'Hello there.', reason: 'stop' }), 'Hello there.');
assert.equal(spokenReply({ text: 'Spoken. <jarvis_hud>{"title":"x","chips":[]}</jarvis_hud>' }), 'Spoken.');
assert.equal(
spokenReply({
text: 'I will look that up. <tool_call><function=web_search><parameter=query>weather</parameter></function></tool_call>',
}),
'I will look that up.',
);
assert.equal(spokenReply({}), '');
assert.equal(spokenReply('[object Object]'), '');
});
+13 -3
View File
@@ -160,9 +160,17 @@ test('public web search and fetch do not require confirmation', () => {
assert.match(VOICE_SYSTEM_PROMPT, /Follow SOUL\.md, IDENTITY\.md, AGENTS\.md/);
assert.match(VOICE_SYSTEM_PROMPT, /PERSONA\.md/);
assert.doesNotMatch(VOICE_SYSTEM_PROMPT, /User personality notes/);
assert.match(voiceSystemPrompt('Ada', 'Be dry. Skip filler.'), /You are Ada/);
assert.match(voiceSystemPrompt('Ada', 'Be dry. Skip filler.'), /User personality notes/);
assert.match(voiceSystemPrompt('Ada', 'Be dry. Skip filler.'), /Be dry\. Skip filler\./);
assert.doesNotMatch(VOICE_SYSTEM_PROMPT, /\n## Acting\n/);
assert.match(voiceSystemPrompt('Ada', 'Be dry. Skip filler.'), /Your name is Ada/);
assert.match(voiceSystemPrompt('Ada', 'Be dry. Skip filler.'), /\n## Acting\nBe dry\. Skip filler\./);
assert.match(voiceSystemPrompt('Ada', 'Be dry. Skip filler.'), /override SOUL\.md/);
assert.doesNotMatch(voiceSystemPrompt('Ada', 'Be dry. Skip filler.'), /User personality notes/);
assert.doesNotMatch(voiceSystemPrompt('Tony', 'Jarvis, you are acting as Tony Hinchcliffe.'), /You are Tony, a local Ubuntu GNOME voice assistant/);
const roast = voiceSystemPrompt('Tony', 'Jarvis, you are acting as Tony Hinchcliffe, roast comedian.\nYou must never call yourself Jarvis.');
assert.match(roast, /Your name is Tony/);
assert.match(roast, /## Acting/);
assert.match(roast, /never call yourself Jarvis/);
assert.match(roast, /still speak as Tony/);
assert.equal(policy.needsPermission('write_file', 'ask'), true);
assert.equal(policy.isIdentityPath('USER.md'), true);
assert.equal(policy.isIdentityPath('PERSONA.md'), true);
@@ -207,6 +215,8 @@ test('QVAC utility tools are exposed only through the master adapter', () => {
});
test('model profiles select one master model without creating another runtime', () => {
assert.equal(profile('laptop-4gb-mm').model, 'qwen3.5-0.8b');
assert.equal(profile('laptop-4gb-mm').vision, true);
assert.equal(profile('laptop-8gb-mm').model, 'qwen3.5-2b');
assert.equal(profile('laptop-8gb-mm').vision, true);
assert.equal(profile('desktop-gpu').model, 'qwen3.5-9b');
+1
View File
@@ -36,6 +36,7 @@ test('saving one window preserves unrelated changes from another and removes con
assert.deepEqual(merged, { ttsSpeed: 1.5, unrelated: 'kept', ttsEnabled: true });
assert.equal(normalizeSettings(merged, SETTINGS_FIELDS).ttsSpeed, 1.5);
assert.equal(voiceSettings({ modelProfile: 'laptop-8gb-mm' }).modelProfile, 'laptop-8gb-mm');
assert.equal(voiceSettings({ modelProfile: 'laptop-4gb-mm' }).modelProfile, 'laptop-4gb-mm');
});
test('every speech preset uses a real registry asset and passes the installed SDK schema', () => {
+40
View File
@@ -0,0 +1,40 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { profile } from '../daemon/model-profiles.js';
const require = createRequire(import.meta.url);
const catalog = require('../vendor/agent-harness/lib/catalog.js');
const toolParse = require('../vendor/agent-harness/lib/tool-parse.js');
test('Qwen3.5 0.8B and 2B use the qwen35 tool dialect and compact-tool reminder', () => {
assert.equal(profile('laptop-4gb-mm').model, 'qwen3.5-0.8b');
assert.equal(profile('laptop-8gb-mm').model, 'qwen3.5-2b');
for (const id of ['qwen3.5-0.8b', 'qwen3.5-2b']) {
assert.equal(catalog.toolDialectFor(id), 'qwen35');
assert.equal(catalog.findCatalogEntry(id).tools, true);
assert.equal(catalog.isCompactToolModel(id), true);
}
assert.match(toolParse.FORMAT_REMINDER, /<function=TOOL_NAME>/);
const tiny = catalog.filterToolsForModel(
[{ name: 'web_search' }, { name: 'qvac_capability' }, { name: 'cu_drag' }],
'qwen3.5-0.8b',
);
assert.deepEqual(tiny.map((t) => t.name), ['web_search']);
});
test('Qwen3.5 compact models recover tool calls nested in think tags', () => {
const tools = [{ name: 'web_search' }, { name: 'web_fetch' }];
const thinking = `<think>
Need a current answer.
<tool_call>
<function=web_search>
<parameter=query>Ubuntu 26.04 release</parameter>
</function>
</tool_call>
</think>`;
const recovered = toolParse.recover({ thinking, text: '', tools });
assert.equal(recovered.calls.length, 1);
assert.equal(recovered.calls[0].name, 'web_search');
assert.equal(recovered.calls[0].arguments.query, 'Ubuntu 26.04 release');
});