Alphas / app.py
luguog's picture
Create app.py
321c479 verified
import os
import requests
import streamlit as st
from datetime import date
ZENODO_API = "https://zenodo.org/api"
st.set_page_config(
page_title="Zenodo Research Submission Dashboard",
page_icon="πŸ“„",
layout="wide"
)
st.title("Zenodo Research Submission Dashboard")
st.caption("Create a Zenodo draft deposit, upload your manuscript, save metadata, and publish when ready.")
with st.sidebar:
st.header("Zenodo Access")
token_source = st.radio(
"Token source",
["Environment variable", "Paste for this session"],
index=0
)
if token_source == "Environment variable":
token = os.getenv("ZENODO_ACCESS_TOKEN", "")
st.info("Uses ZENODO_ACCESS_TOKEN from your local environment.")
else:
token = st.text_input("Zenodo access token", type="password")
st.warning("Never commit or share your token. If you pasted one into chat or GitHub, revoke it.")
st.subheader("1. Manuscript File")
uploaded_file = st.file_uploader("Upload manuscript PDF", type=["pdf"])
st.subheader("2. Research Metadata")
col1, col2 = st.columns(2)
with col1:
title = st.text_input(
"Title",
value="Bearinglessfull Collateral: A Risk Primitive for Distributed Hedge Capacity"
)
creator_name = st.text_input("Creator name", value="Skrobynets, Joseph")
version = st.text_input("Version", value="0.2")
publication_date = st.date_input("Publication date", value=date.today())
with col2:
upload_type = st.selectbox("Upload type", ["publication"], index=0)
publication_type = st.selectbox(
"Publication type",
[
"workingpaper",
"article",
"preprint",
"report",
"technicalnote",
"other"
],
index=0
)
access_right = st.selectbox("Access right", ["open", "restricted", "closed", "embargoed"], index=0)
license_id = st.text_input("License", value="cc-by-4.0")
description = st.text_area(
"Description / abstract",
value=(
"This working paper introduces Bearinglessfull Collateral, a risk primitive "
"for distributed hedge-capacity systems. The framework evaluates whether "
"collateral is not merely sufficient in nominal value, but structurally "
"resilient across venue distribution, liquidation distance, reserve buffers, "
"rebalance readiness, and access risk. It also introduces the Bearinglessfull "
"Score, AlphaSignalLLM, and a GMX Hedge Adapter as components of a research-only "
"architecture for collateral-aware hedge verification."
),
height=180
)
keywords_text = st.text_area(
"Keywords, one per line",
value="""Bearinglessfull Collateral
Bearinglessfull Score
BFS
collateral topology
hedge capacity
distributed collateral
margin risk
DeFi
market microstructure
LLM-assisted research""",
height=180
)
st.subheader("3. Submission Controls")
if "deposit_id" not in st.session_state:
st.session_state.deposit_id = None
if "bucket_url" not in st.session_state:
st.session_state.bucket_url = None
if "record_url" not in st.session_state:
st.session_state.record_url = None
if "doi" not in st.session_state:
st.session_state.doi = None
def require_token():
if not token:
st.error("Missing Zenodo token. Set ZENODO_ACCESS_TOKEN or paste a token for this session.")
return False
return True
def params():
return {"access_token": token}
metadata_payload = {
"metadata": {
"title": title,
"upload_type": upload_type,
"publication_type": publication_type,
"description": description,
"creators": [{"name": creator_name}],
"keywords": [k.strip() for k in keywords_text.splitlines() if k.strip()],
"version": version,
"publication_date": str(publication_date),
"language": "eng",
"access_right": access_right,
}
}
if access_right == "open":
metadata_payload["metadata"]["license"] = license_id
with st.expander("Preview metadata JSON", expanded=False):
st.json(metadata_payload)
c1, c2, c3, c4 = st.columns(4)
with c1:
if st.button("Create Zenodo Draft", use_container_width=True):
if require_token():
try:
response = requests.post(
f"{ZENODO_API}/deposit/depositions",
params=params(),
json={}
)
response.raise_for_status()
deposit = response.json()
st.session_state.deposit_id = deposit["id"]
st.session_state.bucket_url = deposit["links"]["bucket"]
st.success(f"Draft created: {st.session_state.deposit_id}")
except Exception as e:
st.error(f"Failed to create draft: {e}")
with c2:
if st.button("Upload PDF", use_container_width=True):
if require_token():
if not st.session_state.deposit_id or not st.session_state.bucket_url:
st.error("Create a Zenodo draft first.")
elif uploaded_file is None:
st.error("Upload a PDF first.")
else:
try:
file_name = uploaded_file.name
response = requests.put(
f"{st.session_state.bucket_url}/{file_name}",
params=params(),
data=uploaded_file.getvalue()
)
response.raise_for_status()
st.success(f"Uploaded: {file_name}")
except Exception as e:
st.error(f"Failed to upload file: {e}")
with c3:
if st.button("Save Metadata", use_container_width=True):
if require_token():
if not st.session_state.deposit_id:
st.error("Create a Zenodo draft first.")
else:
try:
response = requests.put(
f"{ZENODO_API}/deposit/depositions/{st.session_state.deposit_id}",
params=params(),
json=metadata_payload
)
response.raise_for_status()
st.success("Metadata saved.")
except Exception as e:
st.error(f"Failed to save metadata: {e}")
with c4:
publish_confirm = st.text_input(
"Type PUBLISH-REAL to enable publishing",
placeholder="PUBLISH-REAL"
)
publish_enabled = publish_confirm == "PUBLISH-REAL"
if st.button("Publish DOI", disabled=not publish_enabled, use_container_width=True):
if require_token():
if not st.session_state.deposit_id:
st.error("Create a Zenodo draft first.")
else:
try:
response = requests.post(
f"{ZENODO_API}/deposit/depositions/{st.session_state.deposit_id}/actions/publish",
params=params()
)
response.raise_for_status()
record = response.json()
st.session_state.doi = record.get("doi")
st.session_state.record_url = record.get("links", {}).get("html")
st.success("Published successfully.")
except Exception as e:
st.error(f"Failed to publish: {e}")
st.subheader("4. Current Submission State")
state_col1, state_col2, state_col3 = st.columns(3)
with state_col1:
st.metric("Deposit ID", st.session_state.deposit_id or "Not created")
with state_col2:
st.metric("DOI", st.session_state.doi or "Not published")
with state_col3:
if st.session_state.record_url:
st.link_button("Open Zenodo Record", st.session_state.record_url)
else:
st.write("No public record yet.")
st.divider()
st.subheader("Recommended Flow")
st.write(
"Create Zenodo Draft β†’ Upload PDF β†’ Save Metadata β†’ inspect metadata β†’ type PUBLISH-REAL β†’ Publish DOI."
)
st.caption(
"Publishing is permanent-ish: Zenodo records are designed for durable citation. "
"Review carefully before minting the DOI."
)