fix memory extraction history affordance (#1447)

This commit is contained in:
Neha Prasad 2026-05-12 23:05:34 +05:30 committed by GitHub
parent 61163d6b92
commit 342ba44383
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 83 additions and 19 deletions

View file

@ -871,17 +871,10 @@ export function MemorySection() {
</div>
<details className="library-group memory-extractions" style={{ marginTop: 16 }}>
<summary
style={{
cursor: 'pointer',
fontWeight: 600,
padding: '6px 0',
display: 'flex',
alignItems: 'center',
gap: 8,
}}
>
<span>{t('settings.memoryExtractions')}</span>
<summary className="memory-details-summary">
<span className="memory-details-title">
{t('settings.memoryExtractions')}
</span>
{extractions.length > 0 ? (
<span className="filter-pill-count">{extractions.length}</span>
) : null}
@ -1037,14 +1030,10 @@ export function MemorySection() {
</details>
<details className="library-group" style={{ marginTop: 16 }}>
<summary
style={{
cursor: 'pointer',
fontWeight: 600,
padding: '6px 0',
}}
>
{t('settings.memoryIndex')}
<summary className="memory-details-summary">
<span className="memory-details-title">
{t('settings.memoryIndex')}
</span>
</summary>
<textarea
value={indexDraft ?? index}

View file

@ -16028,6 +16028,48 @@ body.entry-resizing { cursor: col-resize; user-select: none; }
font-size: 11px;
}
.memory-details-summary {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 0;
cursor: pointer;
font-weight: 600;
list-style: none;
user-select: none;
}
.memory-details-summary::-webkit-details-marker {
display: none;
}
.memory-details-summary::before {
content: '▸';
flex: 0 0 1em;
color: var(--text-faint, #aaa);
font-size: 10px;
transition: transform 120ms ease, color 120ms ease;
}
.library-group[open] > .memory-details-summary::before {
transform: rotate(90deg);
}
.memory-details-summary:hover::before,
.memory-details-summary:focus-visible::before {
color: var(--text-muted, #888);
}
.memory-details-summary:focus-visible {
outline: 2px solid var(--accent, #00946f);
outline-offset: 2px;
border-radius: 4px;
}
.memory-details-title {
min-width: 0;
}
/* Memory section: extraction-history list. One row per recorded LLM
extraction attempt, with phase pill + provider/model meta + preview of
the user message that triggered it. Kept dense (no card) so a burst of

View file

@ -227,6 +227,39 @@ describe('MemorySection', () => {
expect(putBodies).toEqual(['# Memory\n\n- Existing bullet\n- New bullet\n']);
});
it('uses the same expandable affordance for extraction history and memory index', async () => {
globalThis.EventSource = StubEventSource as unknown as typeof EventSource;
globalThis.fetch = vi.fn(async (input: RequestInfo | URL) => {
const url = input.toString();
if (url === '/api/memory') {
return new Response(JSON.stringify({
enabled: true,
rootDir: '/tmp/memory',
index: '# Memory\n',
entries: [],
extraction: null,
}), { status: 200, headers: { 'content-type': 'application/json' } });
}
if (url === '/api/memory/extractions') {
return new Response(JSON.stringify({ extractions: [] }), {
status: 200,
headers: { 'content-type': 'application/json' },
});
}
return new Response(JSON.stringify({}), { status: 404 });
}) as typeof fetch;
renderMemorySection();
const extractionSummary = (await screen.findByText('Extraction history'))
.closest('summary') as HTMLElement;
const indexSummary = screen.getByText('MEMORY.md (index)')
.closest('summary') as HTMLElement;
expect(extractionSummary.className).toContain('memory-details-summary');
expect(indexSummary.className).toContain('memory-details-summary');
});
it('clears extraction history after clicking Clear', async () => {
globalThis.EventSource = StubEventSource as unknown as typeof EventSource;
const deletedUrls: string[] = [];