Releases: Liewzheng/ReviewEngine
Releases · Liewzheng/ReviewEngine
Release list
v0.9.36
Fixed
GET /api/v1/catalog/providers502 when the model catalog upstream is unreachable: the resolution chain (fresh mem → network → stale disk → stale mem) had no terminal fallback, so a parameterless GET 502'd in offline/blocked-egress deployments (Docker) and the UI degraded to presets with「提供商目录不可用」. A curated builtin catalog (9 providers: openai/anthropic/deepseek/google/xai/mistral/groq/openrouter/ollama, real api bases, empty model lists — UIs already fall back to manual entry) now terminates the chain with 200; builtin responses are not cached so the next request retries the network. (src/catalog/mod.rs,src/server/api/catalog.rs)GET /api/v1/system/expertshardcoded"weight": 80: the listing was built from the review-execution expert view with a placeholder weight (and dropped disabled experts), so cards showed 80% and the 平均权重 KPI was wrong until a PUT refreshed them. The listing now readsreview_expertsconfig directly — the same source PUT writes — returning real weights/enabled flags. (src/server/api/system.rs)- 「导出评审」button was dead (no click handler): now exports the currently-filtered history (all pages, same query path as the list) as
review-history-<ts>.jsonvia Blob download, with empty-list tooltip/disabled state and success/failure messages. (frontend/src/views/ReviewHistory.vue) - Queue「取消所有失败任务」is now disabled with a tooltip when there are 0 failed tasks (was a silent no-op). (
frontend/src/views/QueueMonitor.vue) - Config 评审规则「添加模式」→ 取消 no longer leaves a stray empty pattern row (local state reset on cancel/enter/save). (
frontend/src/composables/useConfigForm.ts) - 高级设置
maxReviewDurationSecondsno longer displays a fabricated30when unset: 0 renders as empty with placeholder「0 = 不限制」and round-trips as 0. (frontend/src/views/Configuration.vue)
All found by an exhaustive live UI audit (78 checks across all 7 pages + app chrome, real Chrome via WebBridge) — every button/link exercised; results recorded in reports/test-cases/frontend-test-cases-v9-fullsite-audit-2026-08-25.xlsx.
v0.9.35
Changed
- LLM configuration moved to the LLM page: the
/llmpage is now 状态监控 (provider health, unchanged) on top + LLM 配置 below — theLlmSettingsCardandProvidersSectioncards moved from/config, with their own「编辑配置/保存/取消」lifecycle independent of the Configuration page. Saving issues a sparsePUT /api/v1/configcarrying only thellmkey (other sections — GitLab, Git 平台, rules, advanced — are preserved server-side), then refreshes the provider health cards. ThellmNotConfiguredbanner moved with it; the rerun guidance dialog in Review History now routes to/llm, and the provider card's「配置」button scrolls to the on-page config section./configkeeps GitLab / Git 平台 / 评审规则 / 高级设置 and no longer touches thellmsection on save. (frontend/src/views/LlmStatus.vue,frontend/src/views/Configuration.vue,frontend/src/composables/useConfig.ts,frontend/src/services/config.ts,frontend/src/views/ReviewHistory.vue,frontend/src/components/LlmStatus/ProviderCard.vue,frontend/src/i18n/locales/*)
v0.9.34
Fixed
- Env-sourced LLM credentials leaked into
ui-state.toml: a sparsePUT /api/v1/config(e.g. saving only Git platforms) reconstructed the env-derived LLM entry through the legacy scalar keep-path, relabeled its provider asopenai, and persisted its live API key — the env filter then couldn't recognize the relabeled entry, and on a clean-env restart the entry would resurrect. Three-layer fix:UiConfig::from_app_confignow seeds the stored UI projection with masked (***) secrets (upholding the masked-projection invariant, so sparse PUT merges take the keep-path under the entry's real provider name); post-save mask-sync keys off the effective primary provider; and the env-derived filter inpersist.rsalso matches on secret +api_baseidentity regardless of provider label. Regression tests:sparse_put_never_persists_env_non_openai_entry,sparse_and_full_put_persist_identical_llm,from_applied_filters_relabeled_env_entry,sparse_put_keeps_masked_projection_for_non_openai_primary. (src/server/api/config/{types,put,persist}.rs)
v0.9.33
Added
- Runtime-configurable Git platforms (multi-GitLab): a new
gitPlatformsconfig section — managed from the Web UI (Configuration page → 「Git 平台」 card) orPUT /api/v1/config— registers multiple GitLab instances (name / baseUrl / token / optional webhookSecret + webhookSigningSecret). Review requests and inbound GitLab webhooks are routed to the matching instance by URLhost[:port](host matched case-insensitively, explicit port matched strictly); per-platform webhook secrets are honored for both the legacyX-Gitlab-Tokenheader and GitLab 19.xwebhook-signatureHMAC verification. TheX-Gitlab-Tokenrequest header still overrides, and the legacy singlegitlabconfig section keeps working as the implicit default. (src/models/git_platform.rs,src/models/mod.rs,src/server/api/review/{handlers,resolve}.rs,src/server/gitlab/{mod,handler}.rs,src/server/state.rs) - Hot-reload + persistence of Web-UI config:
PUT /api/v1/configalready applied changes in-memory without restart; it now also persists the effective UI-managed config (LLM providers, Git platforms, rules, advanced) atomically toui-state.toml(0600) in the config dir, replayed at startup through the same code path — restarts no longer lose Web-UI changes. Precedence:config.toml<ui-state.toml< env vars. Secrets sourced from env vars are never persisted intoui-state.toml. (src/server/api/config/{put,persist,helpers,types}.rs,src/server/state.rs,src/cli/app.rs) POST /api/v1/config/git-platforms/test: probes a GitLab instance with{baseUrl, token}— always returns 200 with{ok, version}/{ok: false, error}; a blank or masked token falls back to the stored token of the platform with a matching baseUrl. (src/server/api/config/{mod,put,types}.rs)
Changed
- Docker: the
/app/configbind mount is no longer read-only, so Web-UI config changes (ui-state.toml) persist across container restarts. (docker-compose.yml)
Added (UI)
- 「Git 平台」 management card on the Configuration page: list / add / edit / delete / test-connection for Git platforms, with masked-secret keep semantics and an empty state; i18n keys added in all 6 locales (en/zh-CN/zh-TW/ja/ko/fr). (
frontend/src/components/Config/GitPlatformsSection.vue,frontend/src/views/Configuration.vue,frontend/src/{services,types}/config.ts,frontend/src/composables/useConfigForm.ts,frontend/src/i18n/locales/*)
v0.9.32
Fixed
- Review tasks never carried MR metadata: History showed "Untitled Review"/"unknown" for every gitlab_mr review — nothing ever wrote the fetched
MRInfoback to the task.fetch_mr_infonow deserializes the MR author; the task runner back-fills title/author/branches/commit SHA right after MR resolution (so even failed reviews show real metadata); the orchestrator now receives the real MRInfo instead of a hardcoded "API Review"/"unknown" placeholder (prompts carry the true title/branches). Enqueue-time URL-parsed values win (fill-only-blank). (src/git_provider/gitlab/client.rs,src/server/task_queue.rs,src/server/api/review/{resolve,task}.rs) /api/v1/config/modelsprobe 401 for env-provided LLM configs: the model-list probe used only the request-body key, which is blank or the***mask for env-sourced configs. The handler now falls back to the effective server-side key matching the sameapi_base. (src/server/api/config/helpers.rs)
Added (UI)
- Review score & risk level are finally visible: History table gains a sortable score column (color-coded ≥80/≥60/<60) and the detail drawer header shows score + risk level (+ an "unverified" warning tag when coverage is insufficient). (
frontend/src/views/ReviewHistory.vue,frontend/src/types/history.ts,frontend/src/services/reviews.ts) - Full Comment tab: shows a localized empty state ("该审核未生成评论") instead of a blank box for API-triggered reviews without an MR comment.
- Expert findings render the curated
summarymarkdown in a readable pre-wrap container; the raw LLM YAML moved behind a collapsed "原始响应" toggle. i18n keys added in all 6 locales.
v0.9.31
Fixed
- GitLab MR reviews analyzed an empty diff:
fetch_diffused/merge_requests/:iid/changesand joined the per-changedifffragments, which are headerless patch bodies (they start at@@, nodiff --git/---/+++lines) — the diff parser extracted zero files, so reviews "completed" with 0 findings and a hollow 100/unverified score (verified live against GitLab EE 19.2.4).fetch_diffnow prefers/merge_requests/:iid/raw_diffs(full unified git diff, returned verbatim) and falls back to/changesfor old GitLab versions. (src/git_provider/gitlab/client.rs)
v0.9.30
Added
- Guided LLM configuration when none is usable (previously every review failed deep in the pipeline with "all LLM providers failed / has no api_base set"). A config counts as usable when any entry has a non-empty
api_base.- REST:
GET /api/v1/system/healthnow reports top-levelllmConfigured;POST /api/v1/reviewsand/reviews/{id}/rerunfail fast with 422{"code": "llmNotConfigured", "error": "…"}at enqueue (after request-shape, SSRF, and credential validation — security checks keep precedence) when neither the request nor the server has a usable LLM. - CLI:
review/ask/describe/improve/changelognow exit immediately with a guidance message listing the three configuration paths (review-engine initwizard, the resolved config file path,LLM_CONFIGenv example) instead of failing mid-review. - Web: the Configuration page shows a warning banner (all 6 locales) when
llmConfiguredis false; rerunning a review that hits the 422 opens a confirm dialog offering to jump to the config page. (src/server/api/{system,review/handlers}.rs,src/cli/handlers/review.rs+ all command handlers,frontend/src/views/{Configuration,ReviewHistory}.vue,frontend/src/composables/useReviews.ts,frontend/src/types/dashboard.ts)
- REST:
v0.9.29
Fixed
- Self-hosted GitLab on non-default ports / plain HTTP rejected:
Client::newrejected any MR URL whose host contained:(killing every explicit-port URL, e.g.http://gitlab.internal:8929/…) and always built the API base with hardcodedhttps://(killing plain-HTTP internal installs). URL parsing is now extracted intoClient::parse_mr_url→ParsedMrUrl { scheme, host, project_path, mr_iid }; the URL's own scheme is honored, and an optional:port(digits, 1–65535) is accepted. Hardening kept: userinfo (@),.., empty host, bad ports, and IPv6 literals are rejected with clear messages. Benefits every entry point — RESTgitlab_mrreviews, CLIreview/ask/describe/improve, andGitLabProvider. (src/git_provider/gitlab/client.rs) - Invalid MR URLs now fail fast with 422 at enqueue instead of 202-then-async-failure:
submit_reviewandrerun_reviewvalidate thegitlab_mrURL synchronously and return422 invalid gitlab_mr url: …without creating a task. (src/server/api/review/handlers.rs)
v0.9.28
Fixed
- System Logs row misalignment: WARN/ERROR rows carried a colored left border plus an extra
margin-left: 2px, shifting their content 4px right of INFO rows (ragged left edge). All rows now reserve a constant 2px transparent border slot; warn/error only recolor it — every row's content starts at the same x. (frontend/src/views/SystemLogs.vue) - Log column alignment: timestamp used
min-widthso longer values (ISO strings, verbose locales) pushed the level-tag column right. Timestamp column is now fixed-width (110px; 200px in ISO format via ats-isomodifier) and level tags fixed at 56px — timestamp/tag/message columns align across all rows in every timestamp format. (frontend/src/views/SystemLogs.vue) - Transient SSE drops no longer raise an error notification: the log stream's
onerrorpreviously surfaced a persistent 'SSE 连接错误' ElNotification even though EventSource auto-reconnects seconds later (e.g. after a server restart). It now shows a subtle inline "连接中断,正在重连…" indicator in the toolbar that auto-clears on reconnect (es.onopen); history-load failures still notify as before. Newlogs.reconnectingi18n key in all 6 locales. (frontend/src/composables/useLogs.ts,frontend/src/services/logs.ts,frontend/src/views/SystemLogs.vue)
v0.9.27
Added
- Upgrade download progress: the upgrade dialog now shows a live progress bar, download speed (EMA-smoothed over the 2s status polls), target total size, and estimated remaining time during the 下载中 (downloading) step. Backend:
GET /api/v1/system/upgrade/statusgains a camelCasedownload: { downloadedBytes, totalBytes, startedAt }object (null when no download in flight);download_asset/download_verified_assetaccept an optional cumulative-bytes progress callback; the task layer aggregates one monotonic counter across the binary, checksum, frontend dist, and dist checksum downloads (total known upfront from GitHub asset metadata). Degrades gracefully to the plain step message when progress data is absent. i18n keys (upgrade.downloadSpeed/downloadTotal/downloadEta/etaSeconds/etaMinutesSeconds) added for all 6 locales. (src/server/state.rs,src/upgrade/download.rs,src/server/api/upgrade/{task,start}.rs,frontend/src/components/Upgrade/UpgradeDialog.vue,frontend/src/types/upgrade.ts)