| 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"'); |
| }); |
|
|