mirror of
https://github.com/thegeneralist01/archivr
synced 2026-10-09 12:55:00 +02:00
feat: add summary image consent control
This commit is contained in:
parent
ed3bc56e14
commit
7051d459db
3 changed files with 62 additions and 2 deletions
|
|
@ -42,13 +42,13 @@ export async function fetchEntrySummary(archiveId, entryUid) {
|
|||
// caller polls fetchEntrySummary either way.
|
||||
// The server returns 400 with the exact missing env var name when a provider is
|
||||
// unconfigured, so its body is surfaced verbatim rather than replaced.
|
||||
export async function requestEntrySummary(archiveId, entryUid, { provider, force = false } = {}) {
|
||||
export async function requestEntrySummary(archiveId, entryUid, { provider, force = false, includeImages = false } = {}) {
|
||||
const resp = await fetch(
|
||||
`/api/archives/${archiveId}/entries/${entryUid}/summary`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ provider, force }),
|
||||
body: JSON.stringify({ provider, force, include_images: includeImages }),
|
||||
}
|
||||
);
|
||||
if (!resp.ok) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ export default function ContextRail({ archiveId, selectedEntry, selectedUids, se
|
|||
return sessionStorage.getItem(SUMMARY_PROVIDER_KEY) || SUMMARY_PROVIDERS[0].value
|
||||
} catch { return SUMMARY_PROVIDERS[0].value }
|
||||
})
|
||||
const [includeSummaryImages, setIncludeSummaryImages] = useState(false)
|
||||
const summaryPollRef = useRef(null)
|
||||
|
||||
// ── Bulk-panel state ────────────────────────────────────────────────────
|
||||
|
|
@ -129,6 +130,7 @@ export default function ContextRail({ archiveId, selectedEntry, selectedUids, se
|
|||
setSummary(detail?.latest_summary ?? null)
|
||||
setSummaryError('')
|
||||
setSummaryBusy(false)
|
||||
setIncludeSummaryImages(false)
|
||||
}, [detail?.summary?.entry_uid])
|
||||
|
||||
// Poll only while the latest summary is non-terminal. Anchoring the effect on
|
||||
|
|
@ -173,6 +175,7 @@ export default function ContextRail({ archiveId, selectedEntry, selectedUids, se
|
|||
const res = await requestEntrySummary(archiveId, detail.summary.entry_uid, {
|
||||
provider: summaryProvider,
|
||||
force,
|
||||
includeImages: includeSummaryImages,
|
||||
})
|
||||
if (res.status === 'completed') {
|
||||
// 200 cache hit: the response *is* the row, no polling needed.
|
||||
|
|
@ -192,6 +195,7 @@ export default function ContextRail({ archiveId, selectedEntry, selectedUids, se
|
|||
|
||||
function handleProviderChange(value) {
|
||||
setSummaryProvider(value)
|
||||
if (value === 'claude_cli') setIncludeSummaryImages(false)
|
||||
try { sessionStorage.setItem(SUMMARY_PROVIDER_KEY, value) } catch { /* private mode */ }
|
||||
}
|
||||
|
||||
|
|
@ -615,6 +619,22 @@ export default function ContextRail({ archiveId, selectedEntry, selectedUids, se
|
|||
<option key={p.value} value={p.value}>{p.label}</option>
|
||||
))}
|
||||
</select>
|
||||
<div className={`rail-summary-image-option${summaryProvider === 'claude_cli' ? ' rail-summary-image-option--disabled' : ''}`}>
|
||||
<label className="rail-summary-image-option__label">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={includeSummaryImages}
|
||||
disabled={summaryProvider === 'claude_cli'}
|
||||
onChange={e => setIncludeSummaryImages(e.target.checked)}
|
||||
/>
|
||||
Include attached images
|
||||
</label>
|
||||
<p className="rail-summary-image-option__note">
|
||||
{summaryProvider === 'claude_cli'
|
||||
? 'Claude CLI cannot attach local images. Choose an HTTP provider or Codex CLI.'
|
||||
: 'Selected archived images are sent to the chosen provider. Up to 4 supported images (5 MiB each, 12 MiB total) can be attached; unsupported or oversized artifacts are skipped.'}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
className="rail-rearchive-btn"
|
||||
onClick={() => handleGenerateSummary(!!parsed)}
|
||||
|
|
|
|||
|
|
@ -3285,6 +3285,46 @@ body.has-audio-bar { padding-bottom: 56px; }
|
|||
border: 1px solid var(--line);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.rail-summary-image-option {
|
||||
padding: 7px 8px;
|
||||
color: var(--muted);
|
||||
background: var(--paper);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.rail-summary-image-option__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--ink);
|
||||
font-size: 12.5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rail-summary-image-option__label input[type="checkbox"] {
|
||||
margin: 0;
|
||||
accent-color: var(--accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
.rail-summary-image-option__label input[type="checkbox"]:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.rail-summary-image-option__note {
|
||||
margin: 5px 0 0;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.rail-summary-image-option--disabled {
|
||||
color: var(--muted-2);
|
||||
background: var(--paper);
|
||||
}
|
||||
.rail-summary-image-option--disabled .rail-summary-image-option__label {
|
||||
color: var(--muted-2);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.rail-summary-image-option--disabled .rail-summary-image-option__label input[type="checkbox"] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* ── Text / Markdown preview ────────────────────────────────────────────── */
|
||||
.text-preview {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue