File size: 1,609 Bytes
b8a03fa | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import { buildSystemPrompt } from '../desktop/backend/model-client.js';
import {
formatToolResultForModel,
parseToolCall,
removeToolCallJson,
SOVEREIGN_TOOLS,
} from '../desktop/backend/tools.js';
test('model system prompt exposes only the allowlisted sovereign tools', () => {
const prompt = buildSystemPrompt(SOVEREIGN_TOOLS);
expect(prompt).toContain('Never ask the user for secret keys');
expect(prompt).toContain('workspace.search');
expect(prompt).toContain('repo.verify');
expect(prompt).not.toContain('git push');
expect(prompt).not.toContain('shell');
});
test('model tool call parser accepts raw and fenced JSON requests', () => {
expect(parseToolCall('{"name":"repo.status","input":{}}')).toEqual({
name: 'repo.status',
input: {},
});
expect(parseToolCall([
'```json',
'{"tool_call":{"name":"workspace.read_file","input":{"path":"README.md"}}}',
'```',
].join('\n'))).toEqual({
name: 'workspace.read_file',
input: { path: 'README.md' },
});
});
test('tool call cleanup removes JSON control payloads from chat-visible text', () => {
const fenced = [
'```json',
'{"tool_call":{"name":"repo.status","input":{}}}',
'```',
].join('\n');
expect(removeToolCallJson(fenced)).toBe('');
expect(removeToolCallJson(`Need context.\n\n${fenced}`)).toBe('Need context.');
});
test('tool result formatter returns a structured model followup payload', () => {
expect(formatToolResultForModel(
{ name: 'repo.status', input: {} },
{ name: 'repo.status', ok: true, output: '## main' },
)).toContain('"tool_result"');
});
|