Share pages: lazy, cached, our-own-words article summaries
The /a/<id> page now carries an original short summary so it stands on its own,
without republishing the publisher's article:
- summarize.py: transient SSRF-guarded fetch of the article text → local LLM
writes a 2-4 sentence ORIGINAL summary (our words). Cached in article_summaries
forever; we store only our summary, never the body. Generated lazily (only for
shared/viewed articles), de-duped so concurrent hits don't double-generate.
- /a serves cached-or-pending; when pending it shows a calm "summary on its way,
read at {source}" note and self-polls /api/summary/<id>, swapping the summary
in the moment it's ready (never blocks the page on the batch-tier LLM).
- Share menu warms generation on open so recipients usually get the rich version.
- Container reaches the arbiter at arbiter:8080 over caddy_web (LLM env added to
the API container). 124 tests pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -57,6 +57,11 @@
|
||||
}
|
||||
shareOpen = false;
|
||||
}
|
||||
// Kick off summary generation when the user signals intent to share, so it's
|
||||
// cached by the time a recipient opens the link.
|
||||
function warmSummary() {
|
||||
fetch(`/api/summary/${article.id}`).catch(() => {});
|
||||
}
|
||||
async function copy(text, label) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
@@ -127,7 +132,7 @@
|
||||
</button>
|
||||
{/if}
|
||||
<span class="sharewrap">
|
||||
<button class="share" onclick={() => (shareOpen = !shareOpen)} aria-expanded={shareOpen}>Share</button>
|
||||
<button class="share" onclick={() => { shareOpen = !shareOpen; if (shareOpen) warmSummary(); }} aria-expanded={shareOpen}>Share</button>
|
||||
{#if shareOpen}
|
||||
<button class="backdrop" aria-label="Close" onclick={() => (shareOpen = false)}></button>
|
||||
<div class="sharemenu" role="menu">
|
||||
|
||||
Reference in New Issue
Block a user