File size: 7,150 Bytes
9896c32
aa140ba
 
9896c32
 
26eb7c3
f7727d2
26eb7c3
9896c32
f7727d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ffc3f41
 
c1e8597
26eb7c3
9896c32
d905c00
f7727d2
 
26eb7c3
b9a446a
9896c32
26eb7c3
f7727d2
 
 
 
 
26eb7c3
f7727d2
26eb7c3
f7727d2
26eb7c3
 
9896c32
26eb7c3
9896c32
26eb7c3
c1e8597
9896c32
 
26eb7c3
 
c17eb23
f7727d2
8bfb138
d905c00
 
 
 
 
 
ffc3f41
d905c00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8bfb138
d905c00
 
 
 
 
 
 
 
 
 
 
 
f7727d2
d905c00
 
 
ffc3f41
d905c00
 
26eb7c3
d905c00
 
 
 
 
 
 
 
 
26eb7c3
d905c00
 
 
ffc3f41
26eb7c3
d905c00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f7727d2
 
 
c1e8597
f7727d2
acaddd8
c1e8597
c17eb23
f7727d2
c1e8597
 
 
acaddd8
c1e8597
f7727d2
c1e8597
 
ffc3f41
 
 
 
 
f7727d2
26eb7c3
 
aa140ba
f7727d2
 
 
26eb7c3
9896c32
aa140ba
9896c32
f7727d2
 
 
9896c32
aa140ba
26eb7c3
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
"""
Shared KGX3 API Endpoint – Calling KGX3 on PreprintWatch.com. Uploads research papers to the shared endpoint (secured with X-API-Key),
retrieves a signed temporary link, and sends it to the PreprintWatch KGX3 API. Output: JSON formatted Kuhnian Classification Report
"""

import gradio as gr
import requests, json, pathlib, mimetypes, re

# === CONFIGURATION ===
WP_UPLOAD_URL = "https://preprintwatch.com/wp-json/kgx3/v1/upload"   # your WP REST route
WP_UPLOAD_KEY = "lmsijtadti7tiDD6750xNdN"                             # shared secret
API_ENDPOINT  = "https://preprintwatch.com/wp-json/pw-kgx3/v1/submit" # KGX3 proxy
API_KEY       = "sk-X1zY9wS3-vU4tQ0-rOjH5gK2fE7mN6"                   # internal KGX3 key


# === HELPERS ===
def upload_private_pdf(pdf_path: str) -> str:
    """Upload to WordPress secure uploader and return signed fetch URL."""
    with open(pdf_path, "rb") as f:
        r = requests.post(
            WP_UPLOAD_URL,
            headers={"X-API-Key": WP_UPLOAD_KEY},
            files={"file": f},
            timeout=60
        )
    r.raise_for_status()
    data = r.json()
    if "fetch_url" not in data:
        raise RuntimeError(f"Upload failed: {data}")
    return data["fetch_url"]


# === MAIN WORKFLOW ===
def call_kgx3(title, email, pdf_file, agreement):
    if not agreement:
        return "⚠️ You must accept the disclaimer before running KGX3.", ""
    if not pdf_file:
        return "Please select a PDF file.", ""
    if not email or not re.match(r"[^@]+@[^@]+\.[^@]+", email):
        return "A valid email address is required to run KGX3.", ""

    pdf_path = pdf_file.name
    if not pdf_path.lower().endswith(".pdf"):
        return "Only PDF files are supported.", ""

    # --- Upload to WP and get temporary signed URL ---
    try:
        file_url = upload_private_pdf(pdf_path)
    except Exception as e:
        return f"Upload error: {e}", ""

    # --- Forward to KGX3 ---
    headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
    payload = {"title": title or pathlib.Path(pdf_path).stem, "pdf_url": file_url, "email": email}

    try:
        resp = requests.post(API_ENDPOINT, headers=headers, json=payload, timeout=180)
        try:
            body = json.dumps(resp.json(), indent=2, ensure_ascii=False)
        except Exception:
            body = resp.text
        return body, file_url
    except requests.RequestException as e:
        return f"Request error: {e}", file_url


# === STYLE (high-contrast Matrix aesthetic) ===
FUTURE_CSS = """
/* === UNIVERSAL RESET === */
html, body, .gradio-container, section, div, .form, .gr-block, .gr-panel, .gr-box, .gr-column, .gr-row, .container, .file-preview, .upload-box, .wrap-inner {
  background-color: #000 !important;
  color: #00ff99 !important;
  font-family: 'Courier New', monospace !important;
  box-sizing: border-box;
}

/* === GENERAL TEXT === */
* { color: #00ff99 !important; }
h1, h2, h3, label, .label {
  font-weight: 700 !important;
  text-transform: uppercase;
  border-bottom: 1px solid #00ff99;
  margin-bottom: 6px;
  padding-bottom: 4px;
  letter-spacing: 0.5px;
}

/* === CONTAINERS === */
.gr-box, .gr-panel, .gr-block, .gr-column, .gr-row, .form {
  border: 1px solid #00ff99 !important;
  border-radius: 6px;
  background-color: #000 !important;
  padding: 8px !important;
}

/* === INPUTS & TEXTAREAS === */
input, textarea, select {
  background-color: #000 !important;
  color: #00ff99 !important;
  border: 1px solid #00ff99 !important;
  border-radius: 4px;
  padding: 6px 8px !important;
}
input:focus, textarea:focus {
  outline: none !important;
  border: 1px solid #00ffcc !important;
  background-color: #001a10 !important;
}
::placeholder { color: #00ff99 !important; opacity: 0.6; }

/* === FILE UPLOAD === */
.upload-box, .file-preview, .wrap-inner, .file-preview-container {
  background-color: #000 !important;
  border: 2px solid #00ff99 !important;
  border-radius: 6px !important;
  padding: 10px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  transition: all 0.2s ease-in-out;
}
.upload-box:hover, .file-preview:hover {
  background-color: #001a10 !important;
  border-color: #00ffaa !important;
}

/* === BUTTONS === */
button {
  background-color: #000 !important;
  color: #00ff99 !important;
  border: 2px solid #00ff99 !important;
  border-radius: 4px;
  text-transform: uppercase;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 8px 16px !important;
  transition: all 0.15s ease-in-out;
}
button:hover {
  background-color: #00ff99 !important;
  color: #000 !important;
}

/* === OUTPUT / CODE AREA === */
pre, code, .cm-editor, .cm-content, .cm-line, .output-html, .output-markdown {
  background-color: #000 !important;
  color: #00ff99 !important;
  border: 1px solid #00ff99 !important;
  border-radius: 6px;
  padding: 10px !important;
  font-size: 0.9rem;
}

/* === CHECKBOX === */
input[type=checkbox] {
  accent-color: #00ff99 !important;
  transform: scale(1.2);
}

/* === SCROLLBARS === */
::-webkit-scrollbar { width: 8px; background: #000; }
::-webkit-scrollbar-thumb { background: #00ff99; border-radius: 4px; }

/* === FOOTER === */
footer, .footer, small {
  color: #00ff99 !important;
  opacity: 0.8;
  text-align: center;
  letter-spacing: 0.4px;
}
"""

# === BUILD INTERFACE ===
with gr.Blocks(css=FUTURE_CSS, title="KGX3 Research Analyzer") as demo:
    gr.Markdown("""
    # **KGX3 Engine**
    Upload a scientific preprint PDF. The app sends it to the shared KGX3 API endpoint demonstrating the API function.
    """)

    # --- Disclaimer ---
    gr.Markdown("""
    ### ⚠️ Disclaimer
    By using this interface, you confirm that:
    - You are responsible and accountable for the files you upload.  
    - All uploaded files are automatically deleted within **24 hours**.  
    - System logs of KGX3 activity are retained securely for **up to 60 days** for auditing.  
    - You must ensure that any material you upload is lawful, non-confidential, and free of third-party rights restrictions.
    """)
    agreement = gr.Checkbox(
        label="I have read and accept full responsibility and accountability for the files I upload.",
        value=False
    )

    # --- Layout ---
    with gr.Row():
        with gr.Column(scale=1):
            title_box = gr.Textbox(label="Enter the paper title", placeholder="Enter or paste the paper title")
            email_box = gr.Textbox(label="Email (required)", placeholder="you@example.com")
            file_box  = gr.File(label="Upload PDF", file_types=[".pdf"], type="filepath")
            run_btn   = gr.Button("Run KGX3", variant="primary")
        with gr.Column(scale=1):
            output_json = gr.Code(label="KGX3 Response", language="json")
            output_url  = gr.Textbox(label="Temporary PDF Link", interactive=False)

    run_btn.click(call_kgx3,
                  inputs=[title_box, email_box, file_box, agreement],
                  outputs=[output_json, output_url])

    gr.Markdown("<small>Built on Gradio • Thomas Kuhn Foundation © All rights reserved.</small>")

demo.launch()