mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
fix memory extraction history affordance (#1447)
This commit is contained in:
parent
61163d6b92
commit
342ba44383
3 changed files with 83 additions and 19 deletions
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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[] = [];
|
||||
|
|
|
|||
Loading…
Reference in a new issue