research: publishing → published + artifact download (R1)
Before this commit, approve_publish left topics stuck in 'publishing' forever — the sidebar 'published' bucket was always empty and nothing surfaced the artifact. Two-part fix: State machine — approve_publish now transitions reviewing → publishing → published in one API call. Real async packaging isn't a thing yet because the artifact IS the markdown already written to research_outcomes when the last run completed (topology_worker). The intermediate 'publishing' state is preserved (schema-level trigger stamps published_at on landing there) so we keep the option to detour through it later for pdf render / mirror-to-store / etc. Download endpoint — GET /api/research/:id/artifact returns the latest outcome as text/markdown with Content-Disposition: attachment. Filename sanitizes the topic title to ascii-alnum + dash and appends the outcome version so accumulated revision drafts (post R2) don't clobber. Workspace ownership check via research_topics::get; 404 if no outcome yet (reviewers browsing before a run completes). Frontend — ResearchList shows a green Download icon-button next to Delete when status === 'published'. Clicks trigger a plain anchor download of the .md — no JS blob dance needed since the response is already an attachment. Follow-up queued: pdf render (server-side or client-side of the md), mirror-to-store (S3-ish or Obsidian vault) as an async step during the publishing→published detour.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
// outcomes; topology_runs.research_topic_id is SET NULL).
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Plus, Trash2 } from "lucide-react";
|
||||
import { Download, Plus, Trash2 } from "lucide-react";
|
||||
|
||||
import type { Agent } from "@/lib/api/schemas";
|
||||
import {
|
||||
@@ -316,6 +316,28 @@ export function ResearchList({
|
||||
marginTop: 2,
|
||||
}}
|
||||
>
|
||||
{t.status === "published" ? (
|
||||
<a
|
||||
href={`/api/research/${t.id}/artifact`}
|
||||
title="Download artifact (.md)"
|
||||
aria-label="Download artifact"
|
||||
style={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: 6,
|
||||
border: "1px solid rgba(255,255,255,.08)",
|
||||
background: "transparent",
|
||||
color: "#6fd0c0",
|
||||
cursor: "pointer",
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
textDecoration: "none",
|
||||
}}
|
||||
>
|
||||
<Download aria-hidden size={12} />
|
||||
</a>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
title="Delete topic"
|
||||
|
||||
Reference in New Issue
Block a user