diff --git a/docs/technical_specs.md b/docs/technical_specs.md
index 6943a0f..d25465f 100644
--- a/docs/technical_specs.md
+++ b/docs/technical_specs.md
@@ -761,7 +761,7 @@ All calls use structured JSON output (response_schema defines the expected shape
`llm/schema.rs` builds JSON Schema definitions for:
- Classification/summarization: `{title, summary, category, is_article}`
- Web search: `{category_0: [{title, url, summary}], ...}` with per-category arrays
-- Source link extraction schema is deprecated (link extraction mode is no longer configurable).
+- Source link extraction: handled via heuristic HTML parsing (no LLM schema).
### Error Mapping
diff --git a/frontend/src/api/syntheses.ts b/frontend/src/api/syntheses.ts
index e8fb545..fa5f7c7 100644
--- a/frontend/src/api/syntheses.ts
+++ b/frontend/src/api/syntheses.ts
@@ -85,6 +85,10 @@ export const synthesesApi = {
sendEmail: (id: string, email: string): Promise =>
api.post(`/syntheses/${id}/send-email`, { email } satisfies SendEmailRequest),
+ /** POST /syntheses/generate/:jobId/stop -- request cancellation of an in-progress generation job. */
+ stop: (jobId: string): Promise =>
+ api.post(`/syntheses/generate/${jobId}/stop`),
+
/** Download the synthesis as a Markdown file via {@link fetchFile} + {@link triggerDownload}. */
exportMarkdown: async (id: string): Promise => {
const response = await fetchFile(`/syntheses/${id}/export/markdown`);
diff --git a/frontend/src/pages/GenerateSynthesis.tsx b/frontend/src/pages/GenerateSynthesis.tsx
index ab78967..828054f 100644
--- a/frontend/src/pages/GenerateSynthesis.tsx
+++ b/frontend/src/pages/GenerateSynthesis.tsx
@@ -19,6 +19,7 @@ import type { UserSettings, ProviderConfig, ProgressEvent } from '~/types';
import { createSSEConnection, type SSEConnection, type SSEStatus } from '~/utils/sse';
import { providerSupportsWebSearch } from '~/utils/providers';
import LoadingSpinner from '~/components/ui/LoadingSpinner';
+import Button from '~/components/ui/Button';
/** Metadata for a single generation pipeline step. */
interface StepInfo {
@@ -238,11 +239,7 @@ const GenerateSynthesis: Component = () => {
const id = jobId();
if (!id) return;
try {
- await fetch(`/api/v1/syntheses/generate/${id}/stop`, {
- method: 'POST',
- headers: { 'X-Requested-With': 'XMLHttpRequest' },
- credentials: 'same-origin',
- });
+ await synthesesApi.stop(id);
} catch {
// ignore errors — the pipeline will stop on its own
}
@@ -422,13 +419,13 @@ const GenerateSynthesis: Component = () => {
{/* Stop generation button */}
-
+
@@ -437,28 +434,20 @@ const GenerateSynthesis: Component = () => {
+
+
}
>
-
+