diff --git a/src/__tests__/search-output.test.ts b/src/__tests__/search-output.test.ts index d4e746e..8c028ee 100644 --- a/src/__tests__/search-output.test.ts +++ b/src/__tests__/search-output.test.ts @@ -8,12 +8,12 @@ import { } from '../output/search.js'; describe('formatSourcedAnswer', () => { - it('renders the answer and lists sources', () => { + it('renders the answer and lists every source with its snippet', () => { const response: SourcedAnswer = { answer: 'The answer.', sources: [ - { favicon: 'f', name: 'First', snippet: 's', url: 'https://a.example' }, - { favicon: 'f', name: 'Second', snippet: 's', url: 'https://b.example' }, + { favicon: 'f', name: 'First', snippet: 'Snippet one', url: 'https://a.example' }, + { favicon: 'f', name: 'Second', snippet: 'Snippet two', url: 'https://b.example' }, ], }; @@ -23,17 +23,19 @@ describe('formatSourcedAnswer', () => { '', 'The answer.', '', - 'Sources:', - ' • First', - ' https://a.example', - ' • Second', - ' https://b.example', + 'Sources (2):', + ' 1. First', + ' https://a.example', + ' Snippet one', + ' 2. Second', + ' https://b.example', + ' Snippet two', '', ]); }); - it('caps the source list at five entries', () => { - const sources = Array.from({ length: 8 }, (_, i) => ({ + it('lists all sources without capping the count', () => { + const sources = Array.from({ length: 21 }, (_, i) => ({ favicon: 'f', name: `Source ${i}`, snippet: 's', @@ -42,7 +44,8 @@ describe('formatSourcedAnswer', () => { const lines = formatSourcedAnswer({ answer: 'a', sources }); - expect(lines.filter(line => line.startsWith(' • '))).toHaveLength(5); + expect(lines).toContain('Sources (21):'); + expect(lines.filter(line => /^ {2}\d+\. /.test(line))).toHaveLength(21); }); it('omits the Sources section when there are none', () => { diff --git a/src/output/search.ts b/src/output/search.ts index 6301fc8..5973ee9 100644 --- a/src/output/search.ts +++ b/src/output/search.ts @@ -2,8 +2,6 @@ import type { SearchResults, SourcedAnswer } from 'linkup-sdk'; import type { SearchOutputType } from '../commands/search.js'; import { isRecord } from '../utils.js'; -const MAX_SOURCES = 5; - function assertSourcedAnswer(response: unknown): asserts response is SourcedAnswer { if (!isRecord(response) || typeof response.answer !== 'string') { throw new Error('sourcedAnswer response was not in the expected format'); @@ -39,16 +37,19 @@ function assertSearchResults(response: unknown): asserts response is SearchResul } } -// Render a `sourcedAnswer` response: the markdown answer, then up to 5 sources. +// Render a `sourcedAnswer` response: the markdown answer, then every source. export function formatSourcedAnswer(response: SourcedAnswer): string[] { const lines: string[] = ['', response.answer.trim(), '']; const sources = response.sources ?? []; if (sources.length > 0) { - lines.push('Sources:'); - for (const source of sources.slice(0, MAX_SOURCES)) { - lines.push(` • ${source.name}`, ` ${source.url}`); - } + lines.push(`Sources (${sources.length}):`); + sources.forEach((source, index) => { + lines.push(` ${index + 1}. ${source.name}`, ` ${source.url}`); + if (source.snippet) { + lines.push(` ${source.snippet}`); + } + }); lines.push(''); }