diff --git a/README.md b/README.md index d4a674cd..2d7fe089 100644 --- a/README.md +++ b/README.md @@ -169,51 +169,10 @@ python main.py review --title "..." --abstract "..." ## Architecture -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Clients: Web (Next.js) · CLI (Ink) · ARQ Cron · Push │ -└────────────────────────────┬────────────────────────────────────┘ - ▼ -┌─────────────────── FastAPI Gateway (SSE) ───────────────────────┐ -│ /search /daily /analyze /track /review /gen-code /chat │ -└────────────────────────────┬────────────────────────────────────┘ - ▼ -┌─ Application ────────────────────────────────────────────────────┐ -│ Workflows: TopicSearch · DailyPaper · ScholarPipeline · P2C │ -│ Services: LLMService · PaperSearch · EnrichmentPipeline │ -│ Analysis: Judge · TrendAnalyzer · Summarizer · Reviewer │ -└────────────────────────────┬─────────────────────────────────────┘ - ▼ -┌─ Domain ─────────────────────────────────────────────────────────┐ -│ Paper · Scholar · Track · Feedback · Enrichment · Identity │ -└────────────────────────────┬─────────────────────────────────────┘ - ▼ -┌─ Infrastructure ─────────────────────────────────────────────────┐ -│ Adapters: arXiv / S2 / OpenAlex / papers.cool / HF Daily │ -│ Stores: SQLAlchemy (38 tables) · Alembic · ARQ (Redis) │ -│ LLM: ModelRouter (OpenAI / Anthropic / OpenRouter / Ollama)│ -│ Sandbox: Docker / E2B │ -└──────────────────────────────────────────────────────────────────┘ -``` - -> Full editable diagrams: [Excalidraw](asset/architecture.excalidraw) · [draw.io](asset/architecture.drawio) - -
-Data pipeline + +![Architecture](asset/arc.png) -``` - ┌── papers.cool - ├── arXiv API -Input Queries ──→ ├── HF Daily Papers → Normalize → Dedup → Score - ├── OpenAlex / S2 │ - └── (PaperSearchPort) ┌── DailyPaper Report - ├── LLM Enrichment - ──→ ├── LLM-as-Judge (SSE) - ├── Push (Email/Slack/...) - └── Web UI -``` - -
+> Editable source: [Excalidraw](asset/architecture.excalidraw) · [draw.io](asset/architecture.drawio) ## Module Status diff --git a/asset/arc.png b/asset/arc.png new file mode 100644 index 00000000..47d199bf Binary files /dev/null and b/asset/arc.png differ diff --git a/asset/architecture.excalidraw b/asset/architecture.excalidraw index d401df7a..2a84ab27 100644 --- a/asset/architecture.excalidraw +++ b/asset/architecture.excalidraw @@ -3,29 +3,44 @@ "version": 2, "source": "PaperBot", "elements": [ + { "type": "text", "id": "title", - "x": 300, - "y": 15, - "width": 600, - "height": 36, + "x": 250, + "y": 12, + "width": 700, + "height": 32, "text": "PaperBot System Architecture", "fontSize": 28, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" + }, + { + "type": "text", + "id": "subtitle", + "x": 350, + "y": 46, + "width": 500, + "height": 16, + "text": "Hexagonal / Clean Architecture \u00b7 Domain-Driven Design", + "fontSize": 13, + "fontFamily": 1, + "textAlign": "center", + "strokeColor": "#7a8a9a" }, + { "type": "rectangle", "id": "clients_box", "x": 40, - "y": 70, + "y": 76, "width": 1120, - "height": 110, - "strokeColor": "#364fc7", - "backgroundColor": "#edf2ff", + "height": 106, + "strokeColor": "#2c5282", + "backgroundColor": "#e8eef6", "fillStyle": "solid", "strokeWidth": 2, "roundness": { "type": 3 } @@ -33,25 +48,25 @@ { "type": "text", "id": "clients_label", - "x": 60, - "y": 76, - "width": 120, - "height": 22, + "x": 56, + "y": 82, + "width": 80, + "height": 20, "text": "Clients", - "fontSize": 18, + "fontSize": 16, "fontFamily": 1, - "strokeColor": "#364fc7", - "fontStyle": "bold" + "strokeColor": "#2c5282" }, + { "type": "rectangle", - "id": "web_node", - "x": 70, - "y": 108, - "width": 170, + "id": "web_box", + "x": 60, + "y": 110, + "width": 175, "height": 56, - "strokeColor": "#2b8a3e", - "backgroundColor": "#ebfbee", + "strokeColor": "#3b6ea5", + "backgroundColor": "#d3dff0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -59,25 +74,26 @@ { "type": "text", "id": "web_text", - "x": 82, - "y": 114, - "width": 146, + "x": 72, + "y": 116, + "width": 151, "height": 44, - "text": "\ud83c\udf10 Web Dashboard\n Next.js", + "text": "\ud83c\udf10 Web Dashboard\nNext.js + React", "fontSize": 13, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "cli_node", - "x": 270, - "y": 108, - "width": 170, + "id": "cli_box", + "x": 252, + "y": 110, + "width": 175, "height": 56, - "strokeColor": "#2b8a3e", - "backgroundColor": "#ebfbee", + "strokeColor": "#3b6ea5", + "backgroundColor": "#d3dff0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -85,77 +101,80 @@ { "type": "text", "id": "cli_text", - "x": 282, - "y": 114, - "width": 146, + "x": 264, + "y": 116, + "width": 151, "height": 44, - "text": "\ud83d\udcbb Terminal UI\n Ink / React", + "text": "\ud83d\udcbb Terminal UI\nInk / React CLI", "fontSize": 13, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "cron_node", - "x": 470, - "y": 108, - "width": 170, + "id": "arq_box", + "x": 444, + "y": 110, + "width": 175, "height": 56, - "strokeColor": "#2b8a3e", - "backgroundColor": "#ebfbee", + "strokeColor": "#3b6ea5", + "backgroundColor": "#d3dff0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } }, { "type": "text", - "id": "cron_text", - "x": 482, - "y": 114, - "width": 146, + "id": "arq_text", + "x": 456, + "y": 116, + "width": 151, "height": 44, - "text": "\u23f0 ARQ Worker\n Cron Jobs", + "text": "\u23f0 ARQ Worker\nCron / Queue", "fontSize": 13, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "push_client", - "x": 670, - "y": 108, + "id": "push_box", + "x": 636, + "y": 110, "width": 200, "height": 56, - "strokeColor": "#2b8a3e", - "backgroundColor": "#ebfbee", + "strokeColor": "#3b6ea5", + "backgroundColor": "#d3dff0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } }, { "type": "text", - "id": "push_client_text", - "x": 682, - "y": 114, + "id": "push_text", + "x": 648, + "y": 116, "width": 176, "height": 44, - "text": "\ud83d\udce8 Push Channels\n Email / Slack / DingTalk", + "text": "\ud83d\udce8 Push Channels\nEmail/Slack/DingTalk/TG", "fontSize": 13, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "pycli_node", - "x": 900, - "y": 108, - "width": 170, + "id": "pycli_box", + "x": 853, + "y": 110, + "width": 175, "height": 56, - "strokeColor": "#2b8a3e", - "backgroundColor": "#ebfbee", + "strokeColor": "#3b6ea5", + "backgroundColor": "#d3dff0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -163,90 +182,94 @@ { "type": "text", "id": "pycli_text", - "x": 912, - "y": 114, - "width": 146, + "x": 865, + "y": 116, + "width": 151, "height": 44, - "text": "\ud83d\udc0d Python CLI\n Click", + "text": "\ud83d\udc0d Python CLI\nClick", "fontSize": 13, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "arrow", - "id": "arr1", + "id": "arr_clients_api", "x": 600, - "y": 180, + "y": 182, "width": 0, - "height": 40, - "strokeColor": "#495057", + "height": 32, + "strokeColor": "#5a6a7a", "strokeWidth": 2, - "points": [[0, 0], [0, 40]] + "points": [[0, 0], [0, 32]] }, + { "type": "rectangle", "id": "api_box", - "x": 140, - "y": 230, - "width": 920, - "height": 55, - "strokeColor": "#e67700", - "backgroundColor": "#fff9db", + "x": 120, + "y": 220, + "width": 960, + "height": 56, + "strokeColor": "#2874a6", + "backgroundColor": "#d8e8f5", "fillStyle": "solid", "strokeWidth": 2, "roundness": { "type": 3 } }, { "type": "text", - "id": "api_text", + "id": "api_title", "x": 300, - "y": 238, + "y": 226, "width": 600, "height": 22, "text": "\u26a1 FastAPI Gateway \u2014 SSE Streaming", - "fontSize": 18, + "fontSize": 17, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#e67700" + "strokeColor": "#1a4a6a" }, { "type": "text", "id": "api_routes", - "x": 180, - "y": 262, - "width": 840, + "x": 160, + "y": 250, + "width": 880, "height": 16, - "text": "/search /daily /analyze /track /review /gen-code /chat /memory /context", + "text": "/search /daily /analyze /track /review /gen-code /chat /context /memory /feed", "fontSize": 11, "fontFamily": 3, "textAlign": "center", - "strokeColor": "#868e96" + "strokeColor": "#6a7a8a" }, + { "type": "arrow", - "id": "arr2", + "id": "arr_api_app", "x": 600, - "y": 285, + "y": 276, "width": 0, - "height": 35, - "strokeColor": "#495057", + "height": 28, + "strokeColor": "#5a6a7a", "strokeWidth": 2, - "points": [[0, 0], [0, 35]] + "points": [[0, 0], [0, 28]] }, + { "type": "rectangle", "id": "app_box", "x": 40, - "y": 330, + "y": 310, "width": 1120, - "height": 210, - "strokeColor": "#5f3dc4", - "backgroundColor": "#f3f0ff", + "height": 218, + "strokeColor": "#3d5a80", + "backgroundColor": "#ebeef3", "fillStyle": "solid", "strokeWidth": 2, "roundness": { "type": 3 } @@ -254,39 +277,38 @@ { "type": "text", "id": "app_label", - "x": 60, - "y": 336, - "width": 200, - "height": 22, + "x": 56, + "y": 316, + "width": 180, + "height": 20, "text": "Application Layer", - "fontSize": 18, + "fontSize": 16, "fontFamily": 1, - "strokeColor": "#5f3dc4", - "fontStyle": "bold" + "strokeColor": "#3d5a80" }, { "type": "text", "id": "wf_sublabel", - "x": 60, - "y": 360, - "width": 140, - "height": 16, - "text": "Workflows", - "fontSize": 12, + "x": 56, + "y": 340, + "width": 180, + "height": 14, + "text": "Workflows & Orchestration", + "fontSize": 11, "fontFamily": 1, - "strokeColor": "#862e9c" + "strokeColor": "#4a7093" }, { "type": "rectangle", - "id": "ts_node", - "x": 60, - "y": 380, - "width": 155, - "height": 52, - "strokeColor": "#c92a2a", - "backgroundColor": "#fff5f5", + "id": "ts_box", + "x": 56, + "y": 358, + "width": 163, + "height": 50, + "strokeColor": "#3a6b8f", + "backgroundColor": "#d6e4f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -294,25 +316,26 @@ { "type": "text", "id": "ts_text", - "x": 72, - "y": 388, - "width": 131, - "height": 36, - "text": "\ud83d\udd0d TopicSearch\n Workflow", + "x": 68, + "y": 366, + "width": 139, + "height": 34, + "text": "\ud83d\udd0d TopicSearch\nMulti-Source", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "dp_node", - "x": 230, - "y": 380, - "width": 155, - "height": 52, - "strokeColor": "#c92a2a", - "backgroundColor": "#fff5f5", + "id": "dp_box", + "x": 231, + "y": 358, + "width": 163, + "height": 50, + "strokeColor": "#3a6b8f", + "backgroundColor": "#d6e4f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -320,25 +343,26 @@ { "type": "text", "id": "dp_text", - "x": 242, - "y": 388, - "width": 131, - "height": 36, - "text": "\ud83d\udcf0 DailyPaper\n Reporter", + "x": 243, + "y": 366, + "width": 139, + "height": 34, + "text": "\ud83d\udcf0 DailyPaper\nReport + LLM", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "sp_node", - "x": 400, - "y": 380, - "width": 155, - "height": 52, - "strokeColor": "#c92a2a", - "backgroundColor": "#fff5f5", + "id": "sp_box", + "x": 406, + "y": 358, + "width": 163, + "height": 50, + "strokeColor": "#3a6b8f", + "backgroundColor": "#d6e4f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -346,25 +370,26 @@ { "type": "text", "id": "sp_text", - "x": 412, - "y": 388, - "width": 131, - "height": 36, - "text": "\ud83c\udf93 Scholar\n Pipeline", + "x": 418, + "y": 366, + "width": 139, + "height": 34, + "text": "\ud83c\udf93 Scholar\nPipeline", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "p2c_node", - "x": 570, - "y": 380, - "width": 155, - "height": 52, - "strokeColor": "#c92a2a", - "backgroundColor": "#fff5f5", + "id": "p2c_box", + "x": 581, + "y": 358, + "width": 163, + "height": 50, + "strokeColor": "#3a6b8f", + "backgroundColor": "#d6e4f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -372,25 +397,26 @@ { "type": "text", "id": "p2c_text", - "x": 582, - "y": 388, - "width": 131, - "height": 36, - "text": "\ud83d\udcbb Paper2Code\n ReproAgent", + "x": 593, + "y": 366, + "width": 139, + "height": 34, + "text": "\ud83d\udcbb Paper2Code\nReproAgent", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "ce_node", - "x": 740, - "y": 380, - "width": 165, - "height": 52, - "strokeColor": "#c92a2a", - "backgroundColor": "#fff5f5", + "id": "ce_box", + "x": 756, + "y": 358, + "width": 163, + "height": 50, + "strokeColor": "#3a6b8f", + "backgroundColor": "#d6e4f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -398,25 +424,26 @@ { "type": "text", "id": "ce_text", - "x": 752, - "y": 388, - "width": 141, - "height": 36, - "text": "\ud83e\udde0 Context Engine\n Router + Memory", + "x": 768, + "y": 366, + "width": 139, + "height": 34, + "text": "\ud83e\udde0 Context Engine\nRouter + Rec", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "ps_node", - "x": 920, - "y": 380, - "width": 155, - "height": 52, - "strokeColor": "#c92a2a", - "backgroundColor": "#fff5f5", + "id": "ps_box", + "x": 931, + "y": 358, + "width": 163, + "height": 50, + "strokeColor": "#3a6b8f", + "backgroundColor": "#d6e4f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -424,39 +451,40 @@ { "type": "text", "id": "ps_text", - "x": 932, - "y": 388, - "width": 131, - "height": 36, - "text": "\ud83d\udce2 Push Service\n Notify", + "x": 943, + "y": 366, + "width": 139, + "height": 34, + "text": "\ud83d\udce2 Push Service\nApprise + SMTP", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "text", "id": "ag_sublabel", - "x": 60, - "y": 442, - "width": 200, - "height": 16, - "text": "Analysis / Agents", - "fontSize": 12, + "x": 56, + "y": 418, + "width": 160, + "height": 14, + "text": "Analysis & Agents", + "fontSize": 11, "fontFamily": 1, - "strokeColor": "#862e9c" + "strokeColor": "#566585" }, { "type": "rectangle", - "id": "jg_node", - "x": 60, - "y": 462, - "width": 155, - "height": 52, - "strokeColor": "#d9480f", - "backgroundColor": "#fff4e6", + "id": "jg_box", + "x": 56, + "y": 436, + "width": 163, + "height": 50, + "strokeColor": "#4a6e95", + "backgroundColor": "#dde5f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -464,25 +492,26 @@ { "type": "text", "id": "jg_text", - "x": 72, - "y": 470, - "width": 131, - "height": 36, - "text": "\u2696\ufe0f LLM-as-Judge\n 5-dim Scoring", + "x": 68, + "y": 444, + "width": 139, + "height": 34, + "text": "\u2696\ufe0f LLM-as-Judge\n5-dim Scoring", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "ta_node", - "x": 230, - "y": 462, - "width": 155, - "height": 52, - "strokeColor": "#d9480f", - "backgroundColor": "#fff4e6", + "id": "ta_box", + "x": 231, + "y": 436, + "width": 163, + "height": 50, + "strokeColor": "#4a6e95", + "backgroundColor": "#dde5f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -490,25 +519,26 @@ { "type": "text", "id": "ta_text", - "x": 242, - "y": 470, - "width": 131, - "height": 36, - "text": "\ud83d\udcc8 Trend\n Analyzer", + "x": 243, + "y": 444, + "width": 139, + "height": 34, + "text": "\ud83d\udcc8 Trend\nAnalyzer", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "sm_node", - "x": 400, - "y": 462, - "width": 155, - "height": 52, - "strokeColor": "#d9480f", - "backgroundColor": "#fff4e6", + "id": "sm_box", + "x": 406, + "y": 436, + "width": 163, + "height": 50, + "strokeColor": "#4a6e95", + "backgroundColor": "#dde5f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -516,25 +546,26 @@ { "type": "text", "id": "sm_text", - "x": 412, - "y": 470, - "width": 131, - "height": 36, - "text": "\ud83d\udcdd Paper\n Summarizer", + "x": 418, + "y": 444, + "width": 139, + "height": 34, + "text": "\ud83d\udcdd Paper\nSummarizer", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "rv_node", - "x": 570, - "y": 462, - "width": 155, - "height": 52, - "strokeColor": "#d9480f", - "backgroundColor": "#fff4e6", + "id": "rv_box", + "x": 581, + "y": 436, + "width": 163, + "height": 50, + "strokeColor": "#4a6e95", + "backgroundColor": "#dde5f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -542,25 +573,26 @@ { "type": "text", "id": "rv_text", - "x": 582, - "y": 470, - "width": 131, - "height": 36, - "text": "\ud83d\udcda ReviewerAgent\n DeepReview", + "x": 593, + "y": 444, + "width": 139, + "height": 34, + "text": "\ud83d\udcda ReviewerAgent\nDeep Review", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "vf_node", - "x": 740, - "y": 462, - "width": 165, - "height": 52, - "strokeColor": "#d9480f", - "backgroundColor": "#fff4e6", + "id": "vf_box", + "x": 756, + "y": 436, + "width": 163, + "height": 50, + "strokeColor": "#4a6e95", + "backgroundColor": "#dde5f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -568,25 +600,26 @@ { "type": "text", "id": "vf_text", - "x": 752, - "y": 470, - "width": 141, - "height": 36, - "text": "\u2705 Verification\n Agent", + "x": 768, + "y": 444, + "width": 139, + "height": 34, + "text": "\u2705 Verification\nAgent", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "mm_node", - "x": 920, - "y": 462, - "width": 155, - "height": 52, - "strokeColor": "#d9480f", - "backgroundColor": "#fff4e6", + "id": "mm_box", + "x": 931, + "y": 436, + "width": 163, + "height": 50, + "strokeColor": "#4a6e95", + "backgroundColor": "#dde5f0", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -594,38 +627,120 @@ { "type": "text", "id": "mm_text", - "x": 932, - "y": 470, - "width": 131, - "height": 36, - "text": "\ud83d\udce5 Memory\n Middleware", + "x": 943, + "y": 444, + "width": 139, + "height": 34, + "text": "\ud83d\udce5 Memory\nMiddleware", "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" + }, + + + { + "type": "line", + "id": "ports_line", + "x": 80, + "y": 500, + "width": 1040, + "height": 0, + "strokeColor": "#a0b0c0", + "strokeWidth": 1, + "strokeStyle": "dashed", + "points": [[0, 0], [1040, 0]] + }, + { + "type": "text", + "id": "ports_text", + "x": 180, + "y": 504, + "width": 840, + "height": 14, + "text": "Ports: PaperSearchPort \u00b7 EnrichmentPort \u00b7 EventLogPort \u00b7 FeedbackPort \u00b7 PaperRegistryPort", + "fontSize": 10, + "fontFamily": 3, + "textAlign": "center", + "strokeColor": "#8090a0" + }, + + + { + "type": "arrow", + "id": "arr_app_domain", + "x": 600, + "y": 528, + "width": 0, + "height": 28, + "strokeColor": "#5a6a7a", + "strokeWidth": 2, + "points": [[0, 0], [0, 28]] + }, + + + { + "type": "rectangle", + "id": "domain_box", + "x": 120, + "y": 562, + "width": 960, + "height": 52, + "strokeColor": "#8a6d20", + "backgroundColor": "#faf3e0", + "fillStyle": "solid", + "strokeWidth": 2, + "roundness": { "type": 3 } + }, + { + "type": "text", + "id": "domain_label", + "x": 140, + "y": 568, + "width": 120, + "height": 18, + "text": "\ud83c\udfdb\ufe0f Domain", + "fontSize": 15, + "fontFamily": 1, + "strokeColor": "#7a5f18" + }, + { + "type": "text", + "id": "domain_models", + "x": 280, + "y": 572, + "width": 780, + "height": 32, + "text": "Paper \u00b7 Scholar \u00b7 Track \u00b7 Feedback \u00b7 Enrichment \u00b7 Identity \u00b7 Harvest \u00b7 Session", + "fontSize": 13, + "fontFamily": 1, + "textAlign": "center", + "strokeColor": "#5a4a20" }, + { "type": "arrow", - "id": "arr3", + "id": "arr_domain_infra", "x": 600, - "y": 540, + "y": 614, "width": 0, - "height": 35, - "strokeColor": "#495057", + "height": 28, + "strokeColor": "#5a6a7a", "strokeWidth": 2, - "points": [[0, 0], [0, 35]] + "points": [[0, 0], [0, 28]] }, + { "type": "rectangle", "id": "infra_box", "x": 40, - "y": 585, + "y": 648, "width": 1120, - "height": 95, - "strokeColor": "#495057", - "backgroundColor": "#f1f3f5", + "height": 92, + "strokeColor": "#505a65", + "backgroundColor": "#eceef0", "fillStyle": "solid", "strokeWidth": 2, "roundness": { "type": 3 } @@ -633,25 +748,25 @@ { "type": "text", "id": "infra_label", - "x": 60, - "y": 591, - "width": 200, - "height": 22, + "x": 56, + "y": 654, + "width": 180, + "height": 20, "text": "Infrastructure", - "fontSize": 18, + "fontSize": 16, "fontFamily": 1, - "strokeColor": "#495057", - "fontStyle": "bold" + "strokeColor": "#505a65" }, + { "type": "rectangle", - "id": "mr_node", - "x": 60, - "y": 618, - "width": 180, - "height": 48, - "strokeColor": "#0b7285", - "backgroundColor": "#e3fafc", + "id": "mr_box", + "x": 56, + "y": 680, + "width": 200, + "height": 46, + "strokeColor": "#5a7080", + "backgroundColor": "#e0e5ea", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -659,25 +774,26 @@ { "type": "text", "id": "mr_text", - "x": 72, - "y": 626, - "width": 156, - "height": 32, - "text": "\ud83e\udd16 ModelRouter\nOpenAI / NIM / OR", - "fontSize": 12, + "x": 68, + "y": 686, + "width": 176, + "height": 34, + "text": "\ud83e\udd16 ModelRouter\nOpenAI / Anthropic / Ollama", + "fontSize": 11, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "db_node", - "x": 260, - "y": 618, - "width": 180, - "height": 48, - "strokeColor": "#0b7285", - "backgroundColor": "#e3fafc", + "id": "db_box", + "x": 272, + "y": 680, + "width": 200, + "height": 46, + "strokeColor": "#5a7080", + "backgroundColor": "#e0e5ea", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -685,25 +801,26 @@ { "type": "text", "id": "db_text", - "x": 272, - "y": 626, - "width": 156, - "height": 32, - "text": "\ud83d\uddc4\ufe0f SQLite / Alembic\n Event Log + Memory", - "fontSize": 12, + "x": 284, + "y": 686, + "width": 176, + "height": 34, + "text": "\ud83d\uddc4\ufe0f SQLAlchemy (38 tables)\nAlembic Migrations", + "fontSize": 11, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "q_node", - "x": 460, - "y": 618, - "width": 180, - "height": 48, - "strokeColor": "#0b7285", - "backgroundColor": "#e3fafc", + "id": "q_box", + "x": 488, + "y": 680, + "width": 200, + "height": 46, + "strokeColor": "#5a7080", + "backgroundColor": "#e0e5ea", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -711,25 +828,26 @@ { "type": "text", "id": "q_text", - "x": 472, - "y": 626, - "width": 156, - "height": 32, - "text": "\ud83d\udd04 ARQ Queue\n Redis", - "fontSize": 12, + "x": 500, + "y": 686, + "width": 176, + "height": 34, + "text": "\ud83d\udd04 ARQ Queue\nRedis", + "fontSize": 11, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "sb_node", - "x": 660, - "y": 618, - "width": 180, - "height": 48, - "strokeColor": "#0b7285", - "backgroundColor": "#e3fafc", + "id": "sb_box", + "x": 704, + "y": 680, + "width": 200, + "height": 46, + "strokeColor": "#5a7080", + "backgroundColor": "#e0e5ea", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -737,25 +855,26 @@ { "type": "text", "id": "sb_text", - "x": 672, - "y": 626, - "width": 156, - "height": 32, - "text": "\ud83d\udce6 Sandbox\nDocker / E2B", - "fontSize": 12, + "x": 716, + "y": 686, + "width": 176, + "height": 34, + "text": "\ud83d\udce6 Sandbox Executor\nDocker / E2B", + "fontSize": 11, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "fs_node", - "x": 860, - "y": 618, - "width": 180, - "height": 48, - "strokeColor": "#0b7285", - "backgroundColor": "#e3fafc", + "id": "fs_box", + "x": 920, + "y": 680, + "width": 200, + "height": 46, + "strokeColor": "#5a7080", + "backgroundColor": "#e0e5ea", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -763,39 +882,41 @@ { "type": "text", "id": "fs_text", - "x": 872, - "y": 626, - "width": 156, - "height": 32, + "x": 932, + "y": 686, + "width": 176, + "height": 34, "text": "\ud83d\udcc1 File System\nReports / Cache", - "fontSize": 12, + "fontSize": 11, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "arrow", - "id": "arr4", + "id": "arr_infra_ext", "x": 600, - "y": 680, + "y": 740, "width": 0, - "height": 35, - "strokeColor": "#495057", + "height": 28, + "strokeColor": "#5a6a7a", "strokeWidth": 2, "strokeStyle": "dashed", - "points": [[0, 0], [0, 35]] + "points": [[0, 0], [0, 28]] }, + { "type": "rectangle", "id": "ext_box", "x": 40, - "y": 725, + "y": 774, "width": 1120, - "height": 90, - "strokeColor": "#862e9c", - "backgroundColor": "#f8f0fc", + "height": 76, + "strokeColor": "#5a6878", + "backgroundColor": "#e8eaee", "fillStyle": "solid", "strokeWidth": 2, "roundness": { "type": 3 } @@ -803,25 +924,25 @@ { "type": "text", "id": "ext_label", - "x": 60, - "y": 731, - "width": 200, - "height": 22, + "x": 56, + "y": 780, + "width": 160, + "height": 20, "text": "External Sources", - "fontSize": 18, + "fontSize": 16, "fontFamily": 1, - "strokeColor": "#862e9c", - "fontStyle": "bold" + "strokeColor": "#5a6878" }, + { "type": "rectangle", - "id": "pc_node", - "x": 60, - "y": 760, - "width": 145, - "height": 42, - "strokeColor": "#862e9c", - "backgroundColor": "#e5dbff", + "id": "pc_box", + "x": 56, + "y": 805, + "width": 150, + "height": 36, + "strokeColor": "#607080", + "backgroundColor": "#d8dee6", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -829,25 +950,26 @@ { "type": "text", "id": "pc_text", - "x": 72, - "y": 770, - "width": 121, + "x": 68, + "y": 812, + "width": 126, "height": 22, "text": "\ud83d\udcda papers.cool", - "fontSize": 13, + "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "ax_node", - "x": 225, - "y": 760, - "width": 145, - "height": 42, - "strokeColor": "#862e9c", - "backgroundColor": "#e5dbff", + "id": "ax_box", + "x": 222, + "y": 805, + "width": 150, + "height": 36, + "strokeColor": "#607080", + "backgroundColor": "#d8dee6", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -855,25 +977,26 @@ { "type": "text", "id": "ax_text", - "x": 237, - "y": 770, - "width": 121, + "x": 234, + "y": 812, + "width": 126, "height": 22, "text": "\ud83d\udcc4 arXiv API", - "fontSize": 13, + "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "s2_node", - "x": 390, - "y": 760, - "width": 175, - "height": 42, - "strokeColor": "#862e9c", - "backgroundColor": "#e5dbff", + "id": "s2_box", + "x": 388, + "y": 805, + "width": 170, + "height": 36, + "strokeColor": "#607080", + "backgroundColor": "#d8dee6", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -881,51 +1004,53 @@ { "type": "text", "id": "s2_text", - "x": 402, - "y": 770, - "width": 151, + "x": 400, + "y": 812, + "width": 146, "height": 22, "text": "\ud83c\udf10 Semantic Scholar", - "fontSize": 13, + "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "gh_node", - "x": 585, - "y": 760, - "width": 145, - "height": 42, - "strokeColor": "#862e9c", - "backgroundColor": "#e5dbff", + "id": "oa_box", + "x": 574, + "y": 805, + "width": 150, + "height": 36, + "strokeColor": "#607080", + "backgroundColor": "#d8dee6", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } }, { "type": "text", - "id": "gh_text", - "x": 597, - "y": 770, - "width": 121, + "id": "oa_text", + "x": 586, + "y": 812, + "width": 126, "height": 22, - "text": "\ud83d\udc19 GitHub", - "fontSize": 13, + "text": "\ud83d\udd2c OpenAlex", + "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "hf_node", - "x": 750, - "y": 760, - "width": 155, - "height": 42, - "strokeColor": "#862e9c", - "backgroundColor": "#e5dbff", + "id": "hf_box", + "x": 740, + "y": 805, + "width": 150, + "height": 36, + "strokeColor": "#607080", + "backgroundColor": "#d8dee6", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -933,25 +1058,26 @@ { "type": "text", "id": "hf_text", - "x": 762, - "y": 770, - "width": 131, + "x": 752, + "y": 812, + "width": 126, "height": 22, "text": "\ud83e\udd17 HuggingFace", - "fontSize": 13, + "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" }, + { "type": "rectangle", - "id": "or_node", - "x": 925, - "y": 760, - "width": 155, - "height": 42, - "strokeColor": "#862e9c", - "backgroundColor": "#e5dbff", + "id": "or_box", + "x": 906, + "y": 805, + "width": 150, + "height": 36, + "strokeColor": "#607080", + "backgroundColor": "#d8dee6", "fillStyle": "solid", "strokeWidth": 1.5, "roundness": { "type": 3 } @@ -959,19 +1085,34 @@ { "type": "text", "id": "or_text", - "x": 937, - "y": 770, - "width": 131, + "x": 918, + "y": 812, + "width": 126, "height": 22, "text": "\ud83d\udcdd OpenReview", - "fontSize": 13, + "fontSize": 12, "fontFamily": 1, "textAlign": "center", - "strokeColor": "#1e1e1e" + "strokeColor": "#1a2a3a" + }, + + + { + "type": "text", + "id": "version_label", + "x": 1000, + "y": 855, + "width": 160, + "height": 12, + "text": "v2.0 \u00b7 2026-03", + "fontSize": 10, + "fontFamily": 3, + "textAlign": "right", + "strokeColor": "#a0aab4" } ], "appState": { - "viewBackgroundColor": "#ffffff", + "viewBackgroundColor": "#fafbfc", "gridSize": 20 } }