* feat: activate PR babysitting UI toggles for autofix and trigger mode
Remove the "coming soon" gating on the Autofix Mode, Autofix Severity
Threshold, and Trigger Mode controls in the review settings page so
admins can enable CI auto-fix and review-comment resolution on PRs
that Open SWE opens. The backend (ci_autofix.py, webapp.py webhook
routing) was already fully wired — only the UI was disabled.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: simplify autofix to on/off toggle, remove severity threshold
Replace the four-level AutofixMode (off/low/medium/high) and the
autofix_severity_threshold setting with a single boolean
autofix_enabled toggle. The severity threshold was leftover from the
reviewer finding-severity model and does not apply to CI autofix;
the agent should fix any failing CI and resolve any comments on PRs
it opens.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: move autofix toggle to per-user profile, remove team-level setting
The autofix toggle is now per-user (auto_fix_ci in the user profile)
instead of team-level (admin-only). This uses the existing auto_fix_ci
field that was already in ProfileUpdate but never wired up.
Changes:
- ci_autofix.py: check per-user auto_fix_ci profile flag after
resolving the agent thread's github_login, instead of checking
team-level autofix_enabled before knowing the PR
- webapp.py: removed early is_autofix_enabled() webhook gates; the
per-user check now happens in ci_autofix.py once the thread is found
- team_settings.py: removed autofix_enabled field, is_autofix_enabled()
- cloud-agents.tsx: enabled the auto_fix_ci toggle (was comingSoon)
- review.tsx: removed the admin-level autofix switch
- Updated tests and AGENTS.md
The agent graph (not the reviewer) is what gets dispatched - this was
already correct in ci_autofix.py line 223: client.runs.create(
thread_id, "agent", ...).
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: batch PR babysitting events
Remove the leftover trigger-mode gate from PR babysitting and batch new CI/review events while an agent run is already active so the running agent can handle the latest PR state before finishing. Also moves review-feedback permission checks behind the per-user opt-out and applies the auto-fix profile gate to merge-conflict babysitting.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* fix: consume batched babysitting events
Teach the agent queue middleware to turn pending PR babysitting metadata into an injected instruction for the active run, so batched CI/review events are not dropped while still avoiding duplicate run creation.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* fix: address review findings in PR babysitting batching
- Route batched events through the LangGraph store (read in-process by the
message-queue middleware) instead of a per-model-call threads.get on every
agent thread.
- Only record an attempt / mark the head SHA handled on a real dispatch, not
on a batch, so an event isn't permanently dropped if the in-flight run ends
before consuming it.
- Carry the reviewer's comment through batched review feedback instead of
replacing it with a generic re-check nudge.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: AI-sorted PR review view with diff grouping
Group a PR's changed files into a logical top-to-bottom walkthrough via a best-effort structured-output LLM pass, kicked off concurrently with the reviewer run (~0 added latency) and persisted on reviewer thread metadata. Results render in the review UI behind an AI sorted / file tree toggle that persists across PRs; the view falls back to the file tree when groups are absent or stale.
Adds a grouping-model team default (inherits the Reviewer subagent model when unset) and the admin RolePicker for it.
* feat(reviews): richer AI-sorted explanations + sidebar polish
Sidebar group rows get Devin-style spacing (dividers, padding), a per-group file list (click a file to jump to its diff), inline-code chips in titles, and an accent Read explanation link.
Group explanations are now rich markdown: the grouping prompt feeds per-hunk line ranges and asks for inline code, a short code block, and [path:line](#loc=...) references. The Markdown renderer turns those #loc= links into in-page buttons that scroll the diff to the hunk and highlight the range, reusing the existing selectedLines path.
* fix(reviews): drop stale diff groups from the AI-sorted view
When groups were generated for a previous head, a persisted "ai" view in localStorage still rendered the outdated walkthrough. groupedView now returns null on diff_groups_stale, so the file-tree fallback is used and the view toggle hides until fresh groups arrive.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: chat with your PR on the review page
Add a sandbox-less `chat` graph that answers questions about a single PR
from its diff, the published review findings, and read-only GitHub access.
- agent/chat.py: deepagents graph, no sandbox (default StateBackend, file
mutation + execute tools excluded). PR context is seeded as virtual files
under /pr/; a repo-scoped App token is resolved in-graph.
- tools: read_repo_file, search_repo_code, list_review_findings.
- dashboard/review_chat_api.py + routes: per-user chat thread, LangGraph
stream/commands/state/history proxy pinned to the chat assistant, seeds
diff/findings/overview on first run. Gated by repo access.
- UI: Chat tab wired to a chat-scoped StreamProvider (replaces Coming Soon).
* feat: admin setting for review-chat default model
Add a 'Open SWE Review Chat' default to team settings (default_chat_model /
default_chat_reasoning_effort). get_team_default_model("chat") inherits the
Agent default when unset; the chat graph resolves through it. Admin RolePicker
gains an 'Agent default' inherit option that clears the override.
* feat: multi-conversation review chat (tabs, new chat, history)
Replace the single per-PR chat thread with multiple per-user conversations:
- threads minted client-side; first message persists with a title derived
from the prompt.
- list + delete endpoints; chat panel gets a tab strip (history), new-chat
(+), close (x), refresh, an intro greeting, and suggested prompts.
- get_review_chat now returns availability only (ids are client-minted).
* ui fixes
* ui: review-chat history dropdown, full-width AI replies, resizable side panel
* fix(review-chat): enforce per-user thread ownership on proxy endpoints; reseed PR context on head change
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: CI auto-fix and PR babysitting for agent PRs
Watch CI failures and review feedback on PRs Open SWE opened, then dispatch
confidence-gated fix runs on the originating agent thread. Adds CI webhook
ingestion (check_run/check_suite/workflow_run/status), a per-PR @open-swe
autofix on|off toggle, auto-response to review comments, and a polling
ci_monitor graph that also flags merge conflicts. Gated by the existing
autofix_mode/trigger_mode settings, the enabled-repos opt-in, base-branch and
human-commit skip rules, dedupe, and a per-PR attempt cap.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* fix: address review feedback on CI auto-fix
- Security: gate the no-mention review-feedback path on author trust —
require a trusted author_association (OWNER/MEMBER/COLLABORATOR) plus a
GitHub write/maintain/admin permission check before dispatching a
write-capable agent run, preventing privilege escalation from
read/triage/outside reviewers.
- Auth: reuse the originating PR thread's source + login/email when
dispatching fix runs so the GitHub-token resolver authenticates them in
non-bot-token deployments (bespoke github_ci source failed to resolve).
- Docs: document the Commit statuses: Read-only permission required for the
Status webhook event.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Adds an admin-managed, org-wide review guidelines field to team settings
that the reviewer injects into every PR review across all repos, alongside
the existing per-repo style prompt and AGENTS.md context. Repo-specific
rules take precedence when they conflict.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* fix: include reviewer trace links
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
* feat: move reviewer trace-link toggle to dashboard
Replace the OPEN_SWE_REVIEW_TRACE_LINK_ENABLED env var with a team-level
'Trace Links' toggle in the Open SWE Review dashboard tab. The toggle is
read per-publish via get_team_review_trace_links_enabled(); the per-run
review_trace_link_enabled config override still forces it off.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <51395795+johannes117@users.noreply.github.com>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
* feat: upgrade default agent + reviewer model to Opus 4.8
Replace Opus 4.7 with Opus 4.8 (claude-opus-4-8) as the supported
Anthropic model surfaced in the profile editor and used by the main
agent and reviewer graphs. Effort levels (low/medium/high/xhigh/max)
and the high default are unchanged, matching the official Opus 4.8
docs. Updates eval config comment and tests accordingly.
* fix: provider-aware fallback for stale stored model ids
Dropping claude-opus-4-7 from the supported set meant persisted
profile/team-settings still holding it failed the SUPPORTED_MODEL_IDS
check and fell through to default_model_pair() — a cross-provider jump
to the OpenAI global default.
Add provider_fallback_pair: when a stored id is no longer supported but
its provider still has a supported model, resolve to that provider's
newest supported model (anthropic:claude-opus-4-7 -> 4.8), preserving
effort when valid. Resolution order is now: valid stored pair ->
same-provider fallback -> global default_model_pair(). Profile overrides
keep deferring to the team default when no model is set or the provider
is unknown.
* feat(dashboard): restructure Open SWE Review tab + wire create_prs
Restructures the dashboard around two related changes the reviewer settings
have been asking for:
- Wire profile.create_prs. Defaults to true (opt-out); when off the system
prompt gets a `Pull Request Policy Override` section telling the agent
to push the branch and notify with the branch URL instead of opening a
PR. Removes the noop Slack Notifications / Allow Artifacts / First Name
/ Last Name controls and their schema fields.
- Repositories opt-in for Open SWE Review. New per-team enabled list
stored in the LangGraph Store (`["enabled_review_repos"]`). Every
reviewer webhook chokepoint now goes through `_is_repo_enabled_for_review`
which AND-combines the existing env allowlist with the dashboard list.
Default is empty (opt-in) — admins enable repos per-installation from
the new Repositories page nested under Open SWE Review.
- Open SWE Review tab now mirrors the Cursor "rules" pattern: main page
shows installation rows + a Rules entry; both drill into nested pages
(/review/repositories/$owner and /review/styles) with a back link.
- Adds the new logo/favicon assets shipped from sidebar + html head.
Tests pass with a new autouse fixture (`tests/conftest.py`) that defaults
`is_review_repo_enabled` to True for existing allowlist tests.
* fix(dashboard): make main content scroll independently of the sidebar
Outer flex container was min-h-svh, so it grew with main's content and the
whole page scrolled — sidebar moved with it. Pin to h-svh + overflow-hidden
so the sidebar stays put and only <main> scrolls.
* fix(dashboard): make disabled repo toggles obviously disabled
Switch's disabled state used opacity-50 against a muted background, so
the not-admin state looked nearly identical to the off state. Bump to
opacity-40 + grayscale, and wrap each repo toggle in a span carrying a
native hover tooltip explaining why it's disabled.
* fix(switch): handle base-ui's data-disabled state
base-ui's Switch.Root sets data-disabled (not the HTML disabled attribute)
when disabled, so Tailwind's disabled: variant never matches and the
button keeps its cursor-pointer + clickable look. Mirror the styling
under the data-[disabled] variant and add pointer-events-none so the
disabled state is both visible and actually unclickable.
* feat(dashboard): paginate per-installation repository list
20 repos per page with Prev / page X of Y / Next controls at the bottom.
Pager only renders when there are more than 20 repos. Page resets to 0
when navigating between installations.
* feat(dashboard): global default model selectors for Agent + Reviewer
Adds team-wide default model + reasoning effort for both agents in the
Admin tab so operators can switch models without redeploying.
Resolution chain:
Agent: hardcoded -> LLM_MODEL_ID env -> team default -> user profile
Reviewer: hardcoded -> LLM_MODEL_ID env -> team default -> per-call configurable
Team defaults live in team_settings and are validated against the
SUPPORTED_MODELS allowlist + the model's supported reasoning efforts.
'Inherit from env' clears the override and falls back to LLM_MODEL_ID.
* refactor(models): drop LLM_MODEL_ID env in favour of the team default
The team default is now the single source of truth for the runtime model
choice; per-user (agent) and per-call configurable (reviewer) selections
still win on top. When no admin has touched the team default, it surfaces
the hardcoded fallback (DEFAULT_MODEL_ID + its default effort), so the
admin UI's dropdown is always pre-populated with a sensible value.
The Admin UI loses the 'Inherit from env' option since there is no longer
an env layer to inherit from.
* chore(models): set hardcoded fallback to gpt-5.5 medium
Decouple the team-default boot value (gpt-5.5 / medium) from each model's
ProfileForm-suggested default_effort so we can change one without nudging
the other. The Opus xhigh default for new user profiles is unchanged.
* feat(dashboard): trigger-mode copy, Coming Soon badges, logout in My Settings
- Rename trigger mode 'ready_for_review' -> 'once_per_pr' with new
description copy that matches the screenshot. Legacy stored values
fall back to 'every_push' on read so the UI never shows an unknown
selection.
- Add a 'Coming soon' badge + greyed-out + disabled state on the
controls that don't have runtime consumers yet: Trigger Mode,
Autofix Mode, Autofix Severity Threshold, and Automatically fix CI
failures. SettingsRow grew a comingSoon prop to keep this consistent.
- My Settings drops the noop PR Preferences section and adds a Sign
Out button. preferred_pr_destination is removed from the profile
schema; old records get the field popped on next write.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat(dashboard): refactor UI into Cursor-style sidebar layout
Replace the top-bar AppHeader with a left sidebar that holds the four
primary sections (My Settings, Cloud Agents, Open SWE Review,
Integrations) and the user account menu at the bottom. Admin remains a
hidden route reachable from the sidebar only when is_admin.
UI:
- AppShell + AppSidebar with bottom-anchored avatar/sign-out menu.
- My Settings: profile (first/last name) + PR destination preference.
- Cloud Agents: model/effort, default repo, base branch, branch prefix,
PR toggles (auto-fix CI, create PRs, allow artifacts), Slack
notifications.
- Open SWE Review: trigger mode, draft reviews, PR summaries, autofix
mode + severity threshold, plus the existing per-repo review-style
prompts (was /review-styles).
- Integrations: GitHub install status + Slack/Linear status rows.
- New Switch and Menu primitives.
Backend:
- Extend ProfileUpdate with first_name, last_name, base_branch,
branch_prefix, auto_fix_ci, create_prs, allow_artifacts,
slack_notifications, preferred_pr_destination.
- Add team_settings module + /team-settings GET (any session) / PUT
(admin only) for the reviewer configuration.
* fix(dashboard): replace base-ui Menu with plain dropdown, stabilise Selects
- base-ui's Menu hit an "Invalid hook call / Cannot read properties of
null (reading 'useRef')" crash inside fastComponent under Vite's dep
optimisation. The sidebar account menu is the only consumer, so swap
it for a useState-driven dropdown with click-outside + Esc handling
and drop the unused Menu wrapper.
- Initialise the Open SWE Review settings form with the same defaults
the server returns instead of `null`, so the Selects don't switch
from uncontrolled (`undefined`) to controlled on first data load.
* fix(dashboard): address review feedback on admin overwrite + form reset
- admin PUT /admin/profiles/{login} only sent model/effort/repo from the
admin form. ProfileUpdate's Pydantic defaults then wrote auto_fix_ci /
create_prs / slack_notifications etc back onto the target user's
profile, clobbering whatever they had configured. Switch to
model_dump(exclude_unset=True) and overlay the incoming fields on the
user's existing stored profile so only sent fields change.
- my-settings.tsx and cloud-agents.tsx initialised local state from
profile.data on every change. Because useSaveProfile updates the
cached profile on success, toggling any control would overwrite the
user's typed-but-unsaved input in another field. Guard the
initialisation effect with a ref so it runs once on first load.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>