-
Notifications
You must be signed in to change notification settings - Fork 2.2k
feat: Suggest code review after implementation #6404
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 all commits
aaa4141
2621d32
be554c3
93980b3
97d0c65
36dec7e
6abedaf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| import { Flag } from "@/flag/flag" | ||
| import { Identifier } from "@/id/id" | ||
| import { Question } from "@/question" | ||
| import { Session } from "@/session" | ||
| import { MessageV2 } from "@/session/message-v2" | ||
| import { Review } from "@/kilocode/review/review" | ||
|
|
||
| export namespace ReviewFollowup { | ||
| export const ANSWER_START = "Start code review" | ||
| export const ANSWER_SKIP = "Continue without review" | ||
|
|
||
| async function inject(input: { sessionID: string; model: MessageV2.User["model"]; text: string }) { | ||
| const msg: MessageV2.User = { | ||
| id: Identifier.ascending("message"), | ||
| sessionID: input.sessionID, | ||
| role: "user", | ||
| time: { | ||
| created: Date.now(), | ||
| }, | ||
| agent: "code", | ||
| model: input.model, | ||
| } | ||
| await Session.updateMessage(msg) | ||
| await Session.updatePart({ | ||
| id: Identifier.ascending("part"), | ||
| messageID: msg.id, | ||
| sessionID: input.sessionID, | ||
| type: "text", | ||
| text: input.text, | ||
| synthetic: true, | ||
| } satisfies MessageV2.TextPart) | ||
| } | ||
|
|
||
| function prompt(input: { sessionID: string; abort: AbortSignal }) { | ||
| const promise = Question.ask({ | ||
| sessionID: input.sessionID, | ||
| blocking: Flag.KILO_CLIENT !== "vscode", | ||
| questions: [ | ||
| { | ||
| question: "Start an immediate review of uncommitted changes?", | ||
| header: "Code review", | ||
| custom: false, | ||
| options: [ | ||
| { | ||
| label: ANSWER_START, | ||
| description: "Run a local review for current uncommitted changes", | ||
| }, | ||
| { | ||
| label: ANSWER_SKIP, | ||
| description: "Dismiss the review suggestion and continue", | ||
| }, | ||
| ], | ||
| }, | ||
| ], | ||
| }) | ||
|
|
||
| const listener = () => | ||
| Question.list().then((qs) => { | ||
| const match = qs.find((q) => q.sessionID === input.sessionID) | ||
| if (match) Question.reject(match.id) | ||
| }) | ||
| input.abort.addEventListener("abort", listener, { once: true }) | ||
|
|
||
| return promise | ||
| .catch((error) => { | ||
| if (error instanceof Question.RejectedError) return undefined | ||
| throw error | ||
| }) | ||
| .finally(() => { | ||
| input.abort.removeEventListener("abort", listener) | ||
| }) | ||
| } | ||
|
|
||
| export async function ask(input: { | ||
| sessionID: string | ||
| messages: MessageV2.WithParts[] | ||
| abort: AbortSignal | ||
| }): Promise<"continue" | "break"> { | ||
| if (input.abort.aborted) return "break" | ||
|
|
||
| const user = input.messages | ||
| .slice() | ||
| .reverse() | ||
| .find((msg) => msg.info.role === "user")?.info | ||
| if (!user || user.role !== "user" || !user.model) return "break" | ||
|
|
||
| const answers = await prompt({ sessionID: input.sessionID, abort: input.abort }) | ||
| const answer = answers?.[0]?.[0]?.trim() | ||
| if (answer !== ANSWER_START) return "break" | ||
|
|
||
| const text = await Review.buildReviewPromptUncommitted() | ||
|
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. WARNING: New-file-only changes are missed by the auto-review
|
||
| await inject({ | ||
| sessionID: input.sessionID, | ||
| model: user.model, | ||
| text, | ||
| }) | ||
| return "continue" | ||
| } | ||
| } | ||
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.
WARNING: Tool-attached questions will now render twice
AssistantMessagealready renders questions with atoolcontext inline next to the originating tool call. Because this selector no longer keeps the!q.toolguard, those same questions can also appear in the bottom dock, which duplicates the UI and can surface the wrong prompt when both tool and session questions are pending.