-
Notifications
You must be signed in to change notification settings - Fork 261
feat(web): customisable AI code review agent configs #1143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
18304b0
561ee96
166760f
036f626
6871e3a
c6878cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -137,11 +137,36 @@ By default, the agent does not review PRs and MRs automatically. To enable autom | |||||
|
|
||||||
| You can also trigger a review manually by commenting `/review` on any PR or MR. To use a different command, set `REVIEW_AGENT_REVIEW_COMMAND` to your preferred value (without the leading slash). | ||||||
|
|
||||||
| # Agent configs | ||||||
|
|
||||||
| Agent configs let you customise how the review agent behaves per repository, connection, or your whole org. You can override the model, review command, auto-review behaviour, custom prompt, and context files — all without changing environment variables. | ||||||
|
|
||||||
| Configs are managed on the **Agents** page in the Sourcebot UI. Each config has a **scope**: | ||||||
|
|
||||||
| - **Repo** — applies to specific repositories (highest priority) | ||||||
| - **Connection** — applies to all repos in a specific connection | ||||||
| - **Org** — applies to all repositories in your org (lowest priority, catch-all) | ||||||
|
|
||||||
| When a PR or MR arrives, Sourcebot selects the most specific matching config. If no config exists, the agent falls back to global environment variable defaults. | ||||||
|
|
||||||
| ## Custom prompt | ||||||
|
|
||||||
| Each config can include a custom prompt. Two modes are available: | ||||||
|
|
||||||
| - **Append** (default) — your instructions are added after the built-in review rules. | ||||||
| - **Replace** — your instructions entirely replace the built-in rules. Use this when you want full control over what the agent looks for. | ||||||
|
|
||||||
| ## Context files | ||||||
|
|
||||||
| You can configure one or more repository files to be fetched at review time and injected as additional context for the model. This is useful for encoding project-specific conventions that the model should be aware of when reviewing diffs — for example, preferred error handling patterns, style rules, or areas of the codebase that need extra scrutiny. | ||||||
|
|
||||||
| Set **Context files** in the agent config form to a comma or space separated list of paths relative to the repository root (e.g. `AGENTS.md .sourcebot/review.md`). Files that do not exist in the repository are silently ignored. The files are fetched once per PR from the head commit and included in the context for every diff hunk. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix hyphenation in compound adjective. The phrase "comma or space separated list" should be "comma- or space-separated list" per standard grammar rules for compound adjectives. ✏️ Proposed fix-Set **Context files** in the agent config form to a comma or space separated list of paths relative to the repository root (e.g. `AGENTS.md .sourcebot/review.md`).
+Set **Context files** in the agent config form to a comma- or space-separated list of paths relative to the repository root (e.g. `AGENTS.md .sourcebot/review.md`).📝 Committable suggestion
Suggested change
🧰 Tools🪛 LanguageTool[grammar] ~171-~171: Use a hyphen to join words. (QB_NEW_EN_HYPHEN) 🤖 Prompt for AI Agents |
||||||
|
|
||||||
| # Environment variable reference | ||||||
|
|
||||||
| | Variable | Default | Description | | ||||||
| |---|---|---| | ||||||
| | `REVIEW_AGENT_AUTO_REVIEW_ENABLED` | `false` | Automatically review new and updated PRs/MRs | | ||||||
| | `REVIEW_AGENT_REVIEW_COMMAND` | `review` | Comment command that triggers a manual review (without the `/`) | | ||||||
| | `REVIEW_AGENT_MODEL` | first configured model | `displayName` of the language model to use for reviews | | ||||||
| | `REVIEW_AGENT_LOGGING_ENABLED` | unset | Write prompt and response logs to disk for debugging | | ||||||
| | `REVIEW_AGENT_AUTO_REVIEW_ENABLED` | `false` | Automatically review new and updated PRs/MRs. Can be overridden per agent config. | | ||||||
| | `REVIEW_AGENT_REVIEW_COMMAND` | `review` | Comment command that triggers a manual review (without the `/`). Can be overridden per agent config. | | ||||||
| | `REVIEW_AGENT_MODEL` | first configured model | `displayName` of the language model to use for reviews. Can be overridden per agent config. | | ||||||
| | `REVIEW_AGENT_LOGGING_ENABLED` | unset | Write prompt and response logs to disk for debugging. | | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| -- CreateEnum | ||
| CREATE TYPE "AgentType" AS ENUM ('CODE_REVIEW'); | ||
|
|
||
| -- CreateEnum | ||
| CREATE TYPE "AgentScope" AS ENUM ('ORG', 'CONNECTION', 'REPO'); | ||
|
|
||
| -- CreateEnum | ||
| CREATE TYPE "PromptMode" AS ENUM ('REPLACE', 'APPEND'); | ||
|
|
||
| -- CreateTable | ||
| CREATE TABLE "AgentConfig" ( | ||
| "id" TEXT NOT NULL, | ||
| "orgId" INTEGER NOT NULL, | ||
| "name" TEXT NOT NULL, | ||
| "description" TEXT, | ||
| "type" "AgentType" NOT NULL, | ||
| "enabled" BOOLEAN NOT NULL DEFAULT true, | ||
| "prompt" TEXT, | ||
| "promptMode" "PromptMode" NOT NULL DEFAULT 'APPEND', | ||
| "scope" "AgentScope" NOT NULL, | ||
| "settings" JSONB NOT NULL DEFAULT '{}', | ||
| "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| "updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
|
||
| CONSTRAINT "AgentConfig_pkey" PRIMARY KEY ("id") | ||
| ); | ||
|
|
||
| -- CreateTable | ||
| CREATE TABLE "AgentConfigToRepo" ( | ||
| "agentConfigId" TEXT NOT NULL, | ||
| "repoId" INTEGER NOT NULL, | ||
|
|
||
| CONSTRAINT "AgentConfigToRepo_pkey" PRIMARY KEY ("agentConfigId","repoId") | ||
| ); | ||
|
|
||
| -- CreateTable | ||
| CREATE TABLE "AgentConfigToConnection" ( | ||
| "agentConfigId" TEXT NOT NULL, | ||
| "connectionId" INTEGER NOT NULL, | ||
|
|
||
| CONSTRAINT "AgentConfigToConnection_pkey" PRIMARY KEY ("agentConfigId","connectionId") | ||
| ); | ||
|
|
||
| -- CreateIndex | ||
| CREATE INDEX "AgentConfig_orgId_type_enabled_idx" ON "AgentConfig"("orgId", "type", "enabled"); | ||
|
|
||
| -- CreateIndex | ||
| CREATE UNIQUE INDEX "AgentConfig_orgId_name_key" ON "AgentConfig"("orgId", "name"); | ||
|
|
||
| -- AddForeignKey | ||
| ALTER TABLE "AgentConfig" ADD CONSTRAINT "AgentConfig_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "Org"("id") ON DELETE CASCADE ON UPDATE CASCADE; | ||
|
|
||
| -- AddForeignKey | ||
| ALTER TABLE "AgentConfigToRepo" ADD CONSTRAINT "AgentConfigToRepo_agentConfigId_fkey" FOREIGN KEY ("agentConfigId") REFERENCES "AgentConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; | ||
|
|
||
| -- AddForeignKey | ||
| ALTER TABLE "AgentConfigToRepo" ADD CONSTRAINT "AgentConfigToRepo_repoId_fkey" FOREIGN KEY ("repoId") REFERENCES "Repo"("id") ON DELETE CASCADE ON UPDATE CASCADE; | ||
|
|
||
| -- AddForeignKey | ||
| ALTER TABLE "AgentConfigToConnection" ADD CONSTRAINT "AgentConfigToConnection_agentConfigId_fkey" FOREIGN KEY ("agentConfigId") REFERENCES "AgentConfig"("id") ON DELETE CASCADE ON UPDATE CASCADE; | ||
|
|
||
| -- AddForeignKey | ||
| ALTER TABLE "AgentConfigToConnection" ADD CONSTRAINT "AgentConfigToConnection_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "Connection"("id") ON DELETE CASCADE ON UPDATE CASCADE; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,62 @@ | ||||||||||||||||||
| import { authenticatedPage } from "@/middleware/authenticatedPage"; | ||||||||||||||||||
| import { NavigationMenu } from "@/app/(app)/components/navigationMenu"; | ||||||||||||||||||
| import { AgentConfigForm } from "../agentConfigForm"; | ||||||||||||||||||
| import { notFound } from "next/navigation"; | ||||||||||||||||||
|
|
||||||||||||||||||
| type Props = { | ||||||||||||||||||
| params: Promise<{ agentId: string }>; | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| export default authenticatedPage(async ({ prisma, org }, { params }: Props) => { | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gate config editing to org owners. This page exposes the edit form and config details with plain authentication. Add the owner-role option to Proposed fix+import { OrgRole } from "@sourcebot/db";
...
-export default authenticatedPage(async ({ prisma, org }, { params }: Props) => {
+export default authenticatedPage(async ({ prisma, org }, { params }: Props) => {
const { agentId } = await params;
...
-});
+}, { minRole: OrgRole.OWNER, redirectTo: "/settings" });Based on learnings: Use 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| const { agentId } = await params; | ||||||||||||||||||
|
|
||||||||||||||||||
| const [config, connections, repos] = await Promise.all([ | ||||||||||||||||||
| prisma.agentConfig.findFirst({ | ||||||||||||||||||
| where: { id: agentId, orgId: org.id }, | ||||||||||||||||||
| include: { | ||||||||||||||||||
| repos: { select: { repoId: true } }, | ||||||||||||||||||
| connections: { select: { connectionId: true } }, | ||||||||||||||||||
| }, | ||||||||||||||||||
| }), | ||||||||||||||||||
| prisma.connection.findMany({ | ||||||||||||||||||
| where: { orgId: org.id }, | ||||||||||||||||||
| select: { id: true, name: true, connectionType: true }, | ||||||||||||||||||
| orderBy: { name: "asc" }, | ||||||||||||||||||
| }), | ||||||||||||||||||
| prisma.repo.findMany({ | ||||||||||||||||||
| where: { orgId: org.id }, | ||||||||||||||||||
| select: { id: true, displayName: true, external_id: true, external_codeHostType: true }, | ||||||||||||||||||
| orderBy: { displayName: "asc" }, | ||||||||||||||||||
| }), | ||||||||||||||||||
| ]); | ||||||||||||||||||
|
|
||||||||||||||||||
| if (!config) { | ||||||||||||||||||
| notFound(); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <div className="flex flex-col items-center overflow-hidden min-h-screen"> | ||||||||||||||||||
| <NavigationMenu /> | ||||||||||||||||||
| <div className="w-full max-w-3xl px-4 mt-12 mb-24"> | ||||||||||||||||||
| <h1 className="text-2xl font-semibold text-foreground mb-8">Edit agent config</h1> | ||||||||||||||||||
| <AgentConfigForm | ||||||||||||||||||
| initialValues={{ | ||||||||||||||||||
| id: config.id, | ||||||||||||||||||
| name: config.name, | ||||||||||||||||||
| description: config.description ?? "", | ||||||||||||||||||
| type: config.type, | ||||||||||||||||||
| enabled: config.enabled, | ||||||||||||||||||
| prompt: config.prompt ?? "", | ||||||||||||||||||
| promptMode: config.promptMode, | ||||||||||||||||||
| scope: config.scope, | ||||||||||||||||||
| repoIds: config.repos.map((r) => r.repoId), | ||||||||||||||||||
| connectionIds: config.connections.map((c) => c.connectionId), | ||||||||||||||||||
| settings: config.settings as Record<string, unknown>, | ||||||||||||||||||
| }} | ||||||||||||||||||
| connections={connections} | ||||||||||||||||||
| repos={repos} | ||||||||||||||||||
| /> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ); | ||||||||||||||||||
| }); | ||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace em dashes in bullet list.
Lines 146-148 use em dashes (
—) which are disallowed by the docs style guide. Use a different separator (e.g., a colon or a period after the bolded term).✏️ Proposed fix
As per coding guidelines: "do NOT use em dashes (—)".
📝 Committable suggestion
🤖 Prompt for AI Agents