Skip to content

refactor(mineru): standardize on v4 task API for daily push#229

Merged
jerry609 merged 2 commits into
devfrom
jerry-dev
Mar 4, 2026
Merged

refactor(mineru): standardize on v4 task API for daily push#229
jerry609 merged 2 commits into
devfrom
jerry-dev

Conversation

@jerry609

@jerry609 jerry609 commented Mar 4, 2026

Copy link
Copy Markdown
Owner

Summary

This PR delivers the final MinerU integration hardening for DailyPaper push:

  • Standardize on official MinerU v4 async task API only:
    • POST /extract/task
    • GET /extract/task/{task_id}
  • Remove legacy /extract fallback path.
  • Refactor MineruClient for clearer flow:
    • source URL validation
    • task creation + polling
    • unified API error handling
    • zip artifact parsing to figures + captions
  • Add runtime configuration wiring in CLI + ARQ worker:
    • MINERU_API_BASE_URL
    • MINERU_MODEL_VERSION
    • MINERU_MAX_WAIT_SECONDS
  • Keep report-level safety rule:
    • do not publish .zip#... pseudo image URLs as main_figure.
  • Update docs/config templates (README.md, env.example) and tests.

Linked Work

Validation

  • Syntax check passed (py_compile) on modified Python files.
  • Live MinerU API smoke test passed (real task creation/polling + figure caption extraction).
  • Note: local pytest currently exits with code 139 in this machine environment (process-level crash, no assertion output). Recommend CI runner regression as source of truth.

Copilot AI review requested due to automatic review settings March 4, 2026 07:33
@vercel

vercel Bot commented Mar 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
paper-bot Ready Ready Preview, Comment Mar 4, 2026 7:33am

@coderabbitai

coderabbitai Bot commented Mar 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1ec0bd6e-06cb-46c4-8c47-2ad63a532c3e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jerry-dev

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the DailyPaper push functionality by overhauling its integration with the MinerU Cloud API. The primary goal is to improve the reliability and configurability of figure extraction from PDFs, ensuring a more robust and maintainable system for generating daily paper reports. This refactor moves to a more modern, asynchronous API pattern, which allows for better handling of long-running extraction tasks and provides clearer error feedback.

Highlights

  • MinerU API Standardization: The MinerU integration has been standardized to exclusively use the official MinerU v4 async task API, specifically POST /extract/task for task creation and GET /extract/task/{task_id} for polling task status. The legacy /extract fallback path has been removed.
  • MineruClient Refactoring: The MineruClient class has been refactored to provide a clearer flow for MinerU interactions. This includes source URL validation, robust task creation and polling mechanisms, unified API error handling, and improved parsing of zip artifacts to extract figures and captions.
  • Runtime Configuration: New runtime configuration options have been introduced for MinerU, allowing users to configure MINERU_API_BASE_URL, MINERU_MODEL_VERSION, and MINERU_MAX_WAIT_SECONDS via environment variables or CLI arguments. These configurations are wired into both the CLI and ARQ worker processes.
  • Figure URL Safety Rule: A report-level safety rule has been maintained to prevent publishing .zip#... pseudo image URLs as main_figure, ensuring only directly publishable image URLs are used.
  • Documentation and Tests: The README.md and env.example files have been updated to reflect the new MinerU integration status and configuration options. Unit tests have been added or modified to cover the new URL validation logic, markdown parsing from zip artifacts, and the new ARQ worker parameters.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • README.md
    • Updated the status of MinerU figure extraction and Apprise multi-channel integration to '已集成' (integrated) in the '每日推送' (Daily Push) section.
    • Changed the status of 'Push/Notify' from '🟡 基本可用' (basically available) to '✅ 可用' (available) in the feature table.
    • Marked the 'MinerU PDF 图表提取' (MinerU PDF figure extraction) phase as '已完成' (completed) in the 'Phase 6 — 每日推送优化' section.
  • env.example
    • Added new environment variables for MinerU Cloud API configuration: MINERU_API_BASE_URL, MINERU_MODEL_VERSION, and MINERU_MAX_WAIT_SECONDS.
  • src/paperbot/application/workflows/dailypaper.py
    • Introduced a new helper function _is_publishable_figure_url to validate figure URLs, specifically rejecting .zip artifact URLs.
    • Modified extract_figures_for_report to accept base_url, model_version, and max_wait_seconds parameters for the MinerU client.
    • Applied the _is_publishable_figure_url check when setting the main_figure to ensure only valid URLs are published.
  • src/paperbot/infrastructure/extractors/mineru_client.py
    • Updated the module docstring to reflect the use of MinerU v4 async task API and its constraints.
    • Removed the legacy /extract endpoint call and implemented the new async task flow using POST /extract/task and GET /extract/task/{task_id}.
    • Added _DEFAULT_MODEL_VERSION, _DEFAULT_POLL_INTERVAL_SECONDS, _DEFAULT_MAX_WAIT_SECONDS, and _UNSUPPORTED_HOST_HINTS constants.
    • Refactored the MineruClient constructor to accept model_version, poll_interval_seconds, and max_wait_seconds.
    • Implemented _validate_source_url to enforce http(s) scheme and reject known problematic hosts like GitHub and AWS S3.
    • Added _create_task and _poll_until_done methods to manage the asynchronous MinerU task lifecycle.
    • Introduced _request_json for standardized HTTP request handling and API error checking.
    • Implemented _extract_figures_from_zip to download and parse figures from MinerU-generated zip artifacts, including _parse_figures_from_markdown and _resolve_figure_url helpers.
  • src/paperbot/infrastructure/queue/arq_worker.py
    • Added a new helper function _parse_float_env to safely parse float environment variables.
    • Integrated MINERU_API_BASE_URL, MINERU_MODEL_VERSION, and MINERU_MAX_WAIT_SECONDS environment variables into the cron_daily_papers function.
    • Passed the new MinerU configuration parameters to the daily_papers_job when enqueuing it.
  • src/paperbot/presentation/cli/main.py
    • Added new command-line arguments --mineru-api-base-url, --mineru-model-version, and --mineru-max-wait-seconds to the daily paper parser.
    • Integrated these new CLI arguments and their corresponding environment variables into the _run_daily_paper function to configure the MinerU client.
  • tests/unit/test_arq_daily_papers.py
    • Updated the test test_cron_daily_papers_enqueues_job to set new MinerU environment variables and assert that these parameters are correctly passed to the enqueued job.
  • tests/unit/test_dailypaper.py
    • Imported the new _is_publishable_figure_url function.
    • Added a new test test_publishable_figure_url_rejects_zip_artifacts to verify the URL validation logic.
  • tests/unit/test_mineru_client.py
    • Added test_validate_source_url_requires_http to ensure only HTTP(S) URLs are accepted.
    • Added test_validate_source_url_rejects_github_and_aws to verify that URLs from unsupported hosts are rejected.
    • Added test_extract_figures_rejects_unsupported_host_early to confirm that the client fails early for unsupported URLs without making network calls.
    • Added test_parse_figures_from_markdown_zip_refs to test the parsing of figures from markdown content within zip artifacts.
Activity
  • The pull request author, jerry609, has implemented the changes as described in the summary and provided validation steps, including syntax checks and a live MinerU API smoke test. No other human activity (comments, reviews) is recorded in the provided context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the MinerU integration to standardize on the v4 async task API, enhancing robustness with a new MineruClient and externalized configuration. However, it introduces security concerns related to the handling of external ZIP artifacts, specifically potential Denial of Service (DoS) via Zip Bombs and Server-Side Request Forgery (SSRF) due to insufficient validation of the ZIP download URL. It is recommended to implement size limits for downloads and decompression, and validate external URLs against an allow-list. Additionally, consider removing some redundant type casting for improved code clarity.

Comment on lines +211 to +214
response = client.get(zip_url)
response.raise_for_status()

with zipfile.ZipFile(io.BytesIO(response.content), "r") as zf:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The _extract_figures_from_zip method downloads a ZIP file from an external URL and processes it using zipfile.ZipFile. It reads the content of a markdown file from the ZIP into memory without any size or decompression limits. An attacker could provide a malicious ZIP file (Zip Bomb) that expands to an enormous size, leading to excessive memory consumption and potentially crashing the application (Denial of Service). Consider implementing a limit on the size of the downloaded content and the decompressed data.


def _extract_figures_from_zip(self, client: httpx.Client, zip_url: str) -> List[Figure]:
"""Download MinerU result zip and parse figures from generated markdown."""
response = client.get(zip_url)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The _extract_figures_from_zip method performs a GET request to zip_url, which is obtained from the MinerU API response. There is no validation to ensure that zip_url points to a trusted domain. An attacker who can influence the API response (e.g., by compromising the API or if the user is tricked into using a malicious API base URL) could use this to perform Server-Side Request Forgery (SSRF) attacks against internal network resources. It is recommended to validate that the zip_url belongs to an expected allow-list of domains.

figures_max_items=max(1, int(figures_max_items)),
mineru_api_base_url=mineru_api_base_url,
mineru_model_version=mineru_model_version,
mineru_max_wait_seconds=max(5.0, float(mineru_max_wait_seconds)),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The float() cast here is redundant because mineru_max_wait_seconds is already a float, as returned by _parse_float_env on line 218. You can remove the cast for cleaner code.

This redundant cast also appears on lines 255, 410, and 469.

Suggested change
mineru_max_wait_seconds=max(5.0, float(mineru_max_wait_seconds)),
mineru_max_wait_seconds=max(5.0, mineru_max_wait_seconds),

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the DailyPaper → MinerU integration by standardizing on MinerU v4’s async task API and wiring runtime configuration through the CLI and ARQ worker, while preserving a safety rule that prevents publishing ZIP-artifact pseudo URLs as main_figure.

Changes:

  • Refactor MineruClient to use v4 async task create/poll flow and parse figures either from task payload or downloaded ZIP markdown.
  • Wire MinerU runtime knobs (MINERU_API_BASE_URL, MINERU_MODEL_VERSION, MINERU_MAX_WAIT_SECONDS) through CLI and ARQ worker into the DailyPaper workflow.
  • Add/adjust unit tests and update config/docs templates to reflect the new integration behavior.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/paperbot/infrastructure/extractors/mineru_client.py Switches to v4 task API, adds URL validation, polling, ZIP download + markdown parsing, unified response/error handling.
src/paperbot/application/workflows/dailypaper.py Passes MinerU config into MineruClient and blocks ZIP-artifact URLs from becoming main_figure.
src/paperbot/infrastructure/queue/arq_worker.py Adds env parsing and job wiring for MinerU base URL/model/max-wait seconds.
src/paperbot/presentation/cli/main.py Adds CLI flags and env fallbacks for MinerU base URL/model/max-wait seconds.
tests/unit/test_mineru_client.py Adds tests for source URL validation and markdown ZIP ref parsing.
tests/unit/test_dailypaper.py Adds test for publishable figure URL filter (reject .zip artifacts).
tests/unit/test_arq_daily_papers.py Extends cron enqueue test to assert MinerU config is propagated.
env.example Documents MinerU v4 base URL/model/max-wait env vars.
README.md Updates feature/status text to reflect MinerU/Apprise integration state.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +137 to +142
host = (parsed.netloc or "").lower()
if any(host == hint or host.endswith(f".{hint}") for hint in _UNSUPPORTED_HOST_HINTS):
raise ValueError(
"MinerU Cloud may timeout on github/aws URLs; provide a publicly "
"accessible non-github/non-aws URL"
)

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_validate_source_url() uses parsed.netloc for host checks; netloc includes ports/credentials (e.g., "bucket.s3.amazonaws.com:443"), which will bypass the unsupported host detection. Use parsed.hostname (or split off port) for the github/aws timeout guard so it reliably blocks those hosts.

Copilot uses AI. Check for mistakes.
Comment on lines +179 to +183
err_msg = str(detail.get("err_msg") or "task failed")
raise RuntimeError(err_msg)

time.sleep(self._poll_interval_seconds)

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_poll_until_done() uses time.sleep() inside the polling loop. This client is invoked from the async ARQ job path (daily_papers_job -> extract_figures_for_report), so time.sleep() will block the event loop and reduce worker concurrency. Consider making the MinerU client async (httpx.AsyncClient + await asyncio.sleep) or running the blocking extraction in a thread (e.g., asyncio.to_thread).

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +23
def test_validate_source_url_requires_http():
client = MineruClient(api_key="test-key")
try:
client._validate_source_url("file:///tmp/a.pdf")
assert False, "expected ValueError for non-http source"
except ValueError as exc:
assert "http(s)" in str(exc)

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These exception assertions use a try/except + assert False pattern. The rest of the unit tests in this repo commonly use pytest.raises(..., match=...) for this, which gives clearer failure output and avoids accidentally passing when an unexpected exception is raised earlier/later.

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +37
def test_validate_source_url_rejects_github_and_aws():
client = MineruClient(api_key="test-key")
for url in (
"https://github.com/a/b/raw/main/paper.pdf",
"https://raw.githubusercontent.com/a/b/main/paper.pdf",
"https://bucket.s3.amazonaws.com/paper.pdf",
):
try:
client._validate_source_url(url)
assert False, f"expected ValueError for URL: {url}"
except ValueError as exc:
assert "github/aws" in str(exc)

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: prefer pytest.raises(...) instead of manual try/except + assert False when validating that github/aws URLs are rejected; it keeps the test more idiomatic and makes failures easier to diagnose.

Copilot uses AI. Check for mistakes.
Comment on lines +209 to +215
def _extract_figures_from_zip(self, client: httpx.Client, zip_url: str) -> List[Figure]:
"""Download MinerU result zip and parse figures from generated markdown."""
response = client.get(zip_url)
response.raise_for_status()

with zipfile.ZipFile(io.BytesIO(response.content), "r") as zf:
md_members = [name for name in zf.namelist() if name.lower().endswith(".md")]

Copilot AI Mar 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_extract_figures_from_zip() reads the entire ZIP into memory via response.content + BytesIO. Given the documented input limit (up to 200MB PDFs) the resulting ZIP can be large, which risks high memory usage / OOM in the worker. Prefer streaming the response to a temporary file (httpx.stream) and opening ZipFile from disk, or otherwise enforce a maximum download size.

Copilot uses AI. Check for mistakes.
@jerry609
jerry609 merged commit 66deed1 into dev Mar 4, 2026
8 checks passed
jerry609 added a commit that referenced this pull request Mar 4, 2026
* Feat/daily push epic 179 (#218)

* feat(push): implement Epic #179 — daily push optimization

Multi-channel push infrastructure with structured digest cards:

- #187: Integrate HF upvotes into Judge scoring prompt
- #180: Add digest_card extraction (highlight/method/finding/tags)
  with new LLM prompt, email template rendering, markdown output
- #181: MinerU Cloud API client for PDF figure extraction
- #182: Apprise multi-channel push layer with YAML config
- #183-185: Channel formatters (Telegram MarkdownV2, Discord Rich
  Embed, WeCom markdown+news, Feishu/Lark interactive card)
- #186: RSS 2.0 + Atom feed endpoints (/api/feed/daily.xml, .atom)

Also creates follow-up issues #190 (Push Channel Settings UI)
and #191 (Dashboard Digest Card Enhancement).

56 new tests, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: integrate MinerU figure extraction into CLI and ARQ worker daily-paper workflow

Refs #179

* fix(daily-push): enable MinerU flags in ARQ cron payload (refs #181)

* feat(push): wire channel formatters into apprise digest delivery (refs #182 #183 #184 #185)

* feat(feed): add keyword RSS, feed cache, and figure enclosure support (refs #186)

* feat(mineru): add extraction result cache for daily push figure pipeline (refs #181)

* feat(push): add telegram bot command subscription endpoint (refs #191)

* fix(push): add retry/backoff for channel delivery failures (refs #191)

* feat(hf): add trending modes, cache, and arxiv identity dedupe (refs #193)

* feat(push): add idempotency and error-code mapping for channel delivery (refs #191)

* test(push): add mock channel e2e and failure-injection coverage (refs #191)

* docs(push): add audit script and ops runbook for acceptance closure (refs #192)

* docs: update README for AgentSwarm execution transition

* docs: archive stale docs and rename AgentSwarm todo

* docs: add AgentSwarm design proposal + web Playwright e2e setup

- Add docs/proposals/agentswarm-design.md covering multi-agent
  orchestration architecture, adapter pattern, session management,
  skills ecosystem, and OpenCode/OpenClaw/oMo integration (refs #197, #214)
- Add Playwright e2e test scaffolding for web dashboard (smoke,
  papers, research specs)
- Update web/.gitignore for Playwright artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors (#223)

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors

- 支持内联标题/摘要,以绕过 PaperInputRouter 获取 studio 论文 ID

- 使上下文包生成 SSE 流期间的数据库持久化操作不再致命

- 从库中导入重复论文时显示错误消息

- 将左侧文件面板宽度缩小至约 18%(默认宽度);移除默认模板文件

- 为 Claude CLI 添加 --verbose 标志,以兼容 stream-json 输出

Related to #222

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors
- 修改Gemini AI review代码问题

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors
- 修改Gemini AI review代码问题

---------

Co-authored-by: Jerry Zhang <1772030600@qq.com>

* fix(web): correct package.json scripts JSON syntax

* chore(gitignore): block nested .env secrets and keep examples

* docs(env): add MinerU key and figure extraction env templates

* refactor(mineru): standardize on v4 task API for daily push (#229)

* fix(mineru): support v4 async task extraction flow

* refactor(mineru): standardize on v4 task API for daily push (#179)

* feat(push): render MinerU main figure in email via inline fallback

* docs(readme): update email push demo screenshot

* docs(readme): refresh Phase 6 daily push descriptions

* fix(security): harden runbook allowed-dir path validation

* fix(review): resolve security and reliability findings from AI review

* fix(codeql): harden studio chat project_dir normalization

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Boyu liu <oor2020@163.com>
jerry609 added a commit that referenced this pull request Mar 4, 2026
* Feat/daily push epic 179 (#218)

* feat(push): implement Epic #179 — daily push optimization

Multi-channel push infrastructure with structured digest cards:

- #187: Integrate HF upvotes into Judge scoring prompt
- #180: Add digest_card extraction (highlight/method/finding/tags)
  with new LLM prompt, email template rendering, markdown output
- #181: MinerU Cloud API client for PDF figure extraction
- #182: Apprise multi-channel push layer with YAML config
- #183-185: Channel formatters (Telegram MarkdownV2, Discord Rich
  Embed, WeCom markdown+news, Feishu/Lark interactive card)
- #186: RSS 2.0 + Atom feed endpoints (/api/feed/daily.xml, .atom)

Also creates follow-up issues #190 (Push Channel Settings UI)
and #191 (Dashboard Digest Card Enhancement).

56 new tests, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: integrate MinerU figure extraction into CLI and ARQ worker daily-paper workflow

Refs #179

* fix(daily-push): enable MinerU flags in ARQ cron payload (refs #181)

* feat(push): wire channel formatters into apprise digest delivery (refs #182 #183 #184 #185)

* feat(feed): add keyword RSS, feed cache, and figure enclosure support (refs #186)

* feat(mineru): add extraction result cache for daily push figure pipeline (refs #181)

* feat(push): add telegram bot command subscription endpoint (refs #191)

* fix(push): add retry/backoff for channel delivery failures (refs #191)

* feat(hf): add trending modes, cache, and arxiv identity dedupe (refs #193)

* feat(push): add idempotency and error-code mapping for channel delivery (refs #191)

* test(push): add mock channel e2e and failure-injection coverage (refs #191)

* docs(push): add audit script and ops runbook for acceptance closure (refs #192)

* docs: update README for AgentSwarm execution transition

* docs: archive stale docs and rename AgentSwarm todo

* docs: add AgentSwarm design proposal + web Playwright e2e setup

- Add docs/proposals/agentswarm-design.md covering multi-agent
  orchestration architecture, adapter pattern, session management,
  skills ecosystem, and OpenCode/OpenClaw/oMo integration (refs #197, #214)
- Add Playwright e2e test scaffolding for web dashboard (smoke,
  papers, research specs)
- Update web/.gitignore for Playwright artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors (#223)

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors

- 支持内联标题/摘要,以绕过 PaperInputRouter 获取 studio 论文 ID

- 使上下文包生成 SSE 流期间的数据库持久化操作不再致命

- 从库中导入重复论文时显示错误消息

- 将左侧文件面板宽度缩小至约 18%(默认宽度);移除默认模板文件

- 为 Claude CLI 添加 --verbose 标志,以兼容 stream-json 输出

Related to #222

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors
- 修改Gemini AI review代码问题

* fix(studio): fix context pack generation, duplicate import UX, and CLI chat errors
- 修改Gemini AI review代码问题

---------

Co-authored-by: Jerry Zhang <1772030600@qq.com>

* fix(web): correct package.json scripts JSON syntax

* chore(gitignore): block nested .env secrets and keep examples

* docs(env): add MinerU key and figure extraction env templates

* refactor(mineru): standardize on v4 task API for daily push (#229)

* fix(mineru): support v4 async task extraction flow

* refactor(mineru): standardize on v4 task API for daily push (#179)

* feat(push): render MinerU main figure in email via inline fallback

* docs(readme): update email push demo screenshot

* docs(readme): refresh Phase 6 daily push descriptions

* fix(security): harden runbook allowed-dir path validation

* fix(review): resolve security and reliability findings from AI review

* fix(codeql): harden studio chat project_dir normalization

* docs(readme): restructure README for professional presentation

- Add centered hero header with badges (CI, Roadmap, License, Python, Next.js)
- Replace verbose 18-row feature table with categorized bullet lists
- Move Roadmap Phase 1-6 content to pinned issue #232
- Move module maturity matrix to Roadmap #232
- Consolidate screenshots into collapsible sections
- Remove inline API endpoint table (40+ rows) and directory tree
- Add Contributing section with Roadmap link
- Streamline Getting Started with collapsible config details
- Add repo topics for GitHub discoverability

References: vLLM, Docling, PaperQA2, R2R README patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Boyu liu <oor2020@163.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants