mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-07-09 17:28:58 +00:00
feat(session,viewer): record review mode and diff refs in session
Store ReviewMode, DiffFrom, DiffTo, and DiffCommit in SessionHistory and persist them to JSONL (conditionally, only when non-empty). Display mode in viewer list page and show version details (from/to or commit) on the session detail page based on review mode.
This commit is contained in:
parent
55c6bca1f8
commit
0ac1193040
7 changed files with 121 additions and 19 deletions
|
|
@ -56,6 +56,10 @@ type Args struct {
|
|||
// Commit is a single commit hash to review (vs its parent).
|
||||
Commit string
|
||||
|
||||
// ReviewMode is one of "workspace", "range", or "commit".
|
||||
// When empty, it is derived from From/To/Commit at session creation time.
|
||||
ReviewMode string
|
||||
|
||||
// Template loaded from YAML config file.
|
||||
Template template.Template
|
||||
|
||||
|
|
@ -230,7 +234,16 @@ func New(args Args) *Agent {
|
|||
}
|
||||
if args.Session == nil {
|
||||
gitBranch := detectGitBranch(args.RepoDir)
|
||||
args.Session = session.New(args.RepoDir, gitBranch, args.Model)
|
||||
mode := args.ReviewMode
|
||||
if mode == "" {
|
||||
mode = reviewModeString(args.From, args.To, args.Commit)
|
||||
}
|
||||
args.Session = session.New(args.RepoDir, gitBranch, args.Model, session.SessionOptions{
|
||||
ReviewMode: mode,
|
||||
DiffFrom: args.From,
|
||||
DiffTo: args.To,
|
||||
DiffCommit: args.Commit,
|
||||
})
|
||||
}
|
||||
return &Agent{
|
||||
args: args,
|
||||
|
|
@ -1302,6 +1315,16 @@ func buildMessageXML(msgs []llm.Message) string {
|
|||
return sb.String()
|
||||
}
|
||||
|
||||
func reviewModeString(from, to, commit string) string {
|
||||
if commit != "" {
|
||||
return session.ReviewModeCommit
|
||||
}
|
||||
if from != "" && to != "" {
|
||||
return session.ReviewModeRange
|
||||
}
|
||||
return session.ReviewModeWorkspace
|
||||
}
|
||||
|
||||
// detectGitBranch returns the current git branch name for the given repo, or empty string on failure.
|
||||
func detectGitBranch(repoDir string) string {
|
||||
cmd := exec.Command("git", "-C", repoDir, "rev-parse", "--abbrev-ref", "HEAD")
|
||||
|
|
|
|||
|
|
@ -22,6 +22,12 @@ const (
|
|||
ReLocationTask TaskType = "re_location_task"
|
||||
)
|
||||
|
||||
const (
|
||||
ReviewModeWorkspace = "workspace"
|
||||
ReviewModeRange = "range"
|
||||
ReviewModeCommit = "commit"
|
||||
)
|
||||
|
||||
// SessionHistory is the top-level container for an entire CR run.
|
||||
// It is safe for concurrent use by multiple goroutines.
|
||||
type SessionHistory struct {
|
||||
|
|
@ -30,6 +36,10 @@ type SessionHistory struct {
|
|||
RepoDir string
|
||||
GitBranch string
|
||||
Model string
|
||||
ReviewMode string
|
||||
DiffFrom string
|
||||
DiffTo string
|
||||
DiffCommit string
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
persist *jsonlWriter
|
||||
|
|
@ -81,19 +91,31 @@ type ToolResultRecord struct {
|
|||
Result string
|
||||
}
|
||||
|
||||
// SessionOptions holds optional metadata for a new session.
|
||||
type SessionOptions struct {
|
||||
ReviewMode string
|
||||
DiffFrom string
|
||||
DiffTo string
|
||||
DiffCommit string
|
||||
}
|
||||
|
||||
// New creates a new SessionHistory with the given repo directory.
|
||||
func New(repoDir, gitBranch, model string) *SessionHistory {
|
||||
func New(repoDir, gitBranch, model string, opts SessionOptions) *SessionHistory {
|
||||
sessionID := generateUUID()
|
||||
sh := &SessionHistory{
|
||||
SessionID: sessionID,
|
||||
RepoDir: repoDir,
|
||||
GitBranch: gitBranch,
|
||||
Model: model,
|
||||
ReviewMode: opts.ReviewMode,
|
||||
DiffFrom: opts.DiffFrom,
|
||||
DiffTo: opts.DiffTo,
|
||||
DiffCommit: opts.DiffCommit,
|
||||
StartTime: time.Now(),
|
||||
FileSessions: make(map[string]*FileSession),
|
||||
}
|
||||
|
||||
p, err := newJSONLWriter(sessionID, repoDir, gitBranch, model)
|
||||
p, err := newJSONLWriter(sessionID, repoDir, gitBranch, model, opts)
|
||||
if err != nil {
|
||||
fmt.Printf("[ocr session] warning: failed to create session writer: %v\n", err)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -17,23 +17,31 @@ import (
|
|||
// $HOME/.opencodereview/sessions/<encoded-repo-path>/<session-id>.jsonl.
|
||||
// It is safe for concurrent use by multiple goroutines.
|
||||
type jsonlWriter struct {
|
||||
mu sync.Mutex
|
||||
sessionID string
|
||||
repoDir string
|
||||
gitBranch string
|
||||
model string
|
||||
file *os.File
|
||||
writer *bufio.Writer
|
||||
lastUUID string // tracks chain of records via parentUuid
|
||||
mu sync.Mutex
|
||||
sessionID string
|
||||
repoDir string
|
||||
gitBranch string
|
||||
model string
|
||||
reviewMode string
|
||||
diffFrom string
|
||||
diffTo string
|
||||
diffCommit string
|
||||
file *os.File
|
||||
writer *bufio.Writer
|
||||
lastUUID string // tracks chain of records via parentUuid
|
||||
}
|
||||
|
||||
// newJSONLWriter creates and opens a new JSONL writer for the given session.
|
||||
func newJSONLWriter(sessionID, repoDir, gitBranch, model string) (*jsonlWriter, error) {
|
||||
func newJSONLWriter(sessionID, repoDir, gitBranch, model string, opts SessionOptions) (*jsonlWriter, error) {
|
||||
jw := &jsonlWriter{
|
||||
sessionID: sessionID,
|
||||
repoDir: repoDir,
|
||||
gitBranch: gitBranch,
|
||||
model: model,
|
||||
sessionID: sessionID,
|
||||
repoDir: repoDir,
|
||||
gitBranch: gitBranch,
|
||||
model: model,
|
||||
reviewMode: opts.ReviewMode,
|
||||
diffFrom: opts.DiffFrom,
|
||||
diffTo: opts.DiffTo,
|
||||
diffCommit: opts.DiffCommit,
|
||||
}
|
||||
if err := jw.open(); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -126,6 +134,18 @@ func (jw *jsonlWriter) WriteSessionStart(startTime time.Time) string {
|
|||
"gitBranch": jw.gitBranch,
|
||||
"model": jw.model,
|
||||
}
|
||||
if jw.reviewMode != "" {
|
||||
rec["reviewMode"] = jw.reviewMode
|
||||
}
|
||||
if jw.diffFrom != "" {
|
||||
rec["diffFrom"] = jw.diffFrom
|
||||
}
|
||||
if jw.diffTo != "" {
|
||||
rec["diffTo"] = jw.diffTo
|
||||
}
|
||||
if jw.diffCommit != "" {
|
||||
rec["diffCommit"] = jw.diffCommit
|
||||
}
|
||||
|
||||
jw.mu.Lock()
|
||||
defer jw.mu.Unlock()
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ func TestSetErrorIncrementsCounter(t *testing.T) {
|
|||
|
||||
func TestSetErrorWritesJSONL(t *testing.T) {
|
||||
repoDir := t.TempDir()
|
||||
sh := New(repoDir, "main", "test-model")
|
||||
sh := New(repoDir, "main", "test-model", SessionOptions{ReviewMode: ReviewModeWorkspace})
|
||||
defer sh.Finalize()
|
||||
|
||||
fs := sh.GetOrCreateFileSession("foo.go")
|
||||
|
|
@ -193,7 +193,7 @@ func TestSetErrorWritesJSONL(t *testing.T) {
|
|||
|
||||
func TestSessionEndIncludesFailures(t *testing.T) {
|
||||
repoDir := t.TempDir()
|
||||
sh := New(repoDir, "main", "test-model")
|
||||
sh := New(repoDir, "main", "test-model", SessionOptions{ReviewMode: ReviewModeWorkspace})
|
||||
|
||||
fs := sh.GetOrCreateFileSession("bar.go")
|
||||
for i := 0; i < 3; i++ {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,10 @@ type SessionSummary struct {
|
|||
CWD string
|
||||
GitBranch string
|
||||
Model string
|
||||
ReviewMode string
|
||||
DiffFrom string
|
||||
DiffTo string
|
||||
DiffCommit string
|
||||
FilesReviewed []string
|
||||
DurationSec float64
|
||||
FileCount int
|
||||
|
|
@ -149,6 +153,18 @@ func peekSession(path string) (SessionSummary, error) {
|
|||
if model, ok := rec["model"].(string); ok {
|
||||
summary.Model = model
|
||||
}
|
||||
if rm, ok := rec["reviewMode"].(string); ok {
|
||||
summary.ReviewMode = rm
|
||||
}
|
||||
if v, ok := rec["diffFrom"].(string); ok {
|
||||
summary.DiffFrom = v
|
||||
}
|
||||
if v, ok := rec["diffTo"].(string); ok {
|
||||
summary.DiffTo = v
|
||||
}
|
||||
if v, ok := rec["diffCommit"].(string); ok {
|
||||
summary.DiffCommit = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -274,6 +290,18 @@ func LoadSession(root, encodedRepo, sessionID string) (*ViewSession, error) {
|
|||
if model, ok := rec["model"].(string); ok {
|
||||
vs.Summary.Model = model
|
||||
}
|
||||
if rm, ok := rec["reviewMode"].(string); ok {
|
||||
vs.Summary.ReviewMode = rm
|
||||
}
|
||||
if v, ok := rec["diffFrom"].(string); ok {
|
||||
vs.Summary.DiffFrom = v
|
||||
}
|
||||
if v, ok := rec["diffTo"].(string); ok {
|
||||
vs.Summary.DiffTo = v
|
||||
}
|
||||
if v, ok := rec["diffCommit"].(string); ok {
|
||||
vs.Summary.DiffCommit = v
|
||||
}
|
||||
|
||||
case "llm_request":
|
||||
fp, _ := rec["filePath"].(string)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@
|
|||
<div class="meta">
|
||||
<span><strong>CWD:</strong> {{.Session.Summary.CWD}}</span>
|
||||
<span><strong>Branch:</strong> {{.Session.Summary.GitBranch}}</span>
|
||||
<span><strong>Mode:</strong> {{if .Session.Summary.ReviewMode}}{{.Session.Summary.ReviewMode}}{{else}}-{{end}}</span>
|
||||
{{if eq .Session.Summary.ReviewMode "range"}}
|
||||
<span><strong>From:</strong> <code>{{.Session.Summary.DiffFrom}}</code></span>
|
||||
<span><strong>To:</strong> <code>{{.Session.Summary.DiffTo}}</code></span>
|
||||
{{end}}
|
||||
{{if eq .Session.Summary.ReviewMode "commit"}}
|
||||
<span><strong>Commit:</strong> <code>{{.Session.Summary.DiffCommit}}</code></span>
|
||||
{{end}}
|
||||
<span><strong>Model:</strong> <code>{{.Session.Summary.Model}}</code></span>
|
||||
<span><strong>Duration:</strong> {{formatDuration .Session.Summary.DurationSec}}</span>
|
||||
<span><strong>Files:</strong> {{.Session.Summary.FileCount}}</span>
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@
|
|||
<h2>Sessions: {{.RepoName}}</h2>
|
||||
{{if .Sessions}}
|
||||
<table class="table">
|
||||
<thead><tr><th>Session ID</th><th>Branch</th><th>Model</th><th>Files</th><th>Duration</th><th>Started At</th></tr></thead>
|
||||
<thead><tr><th>Session ID</th><th>Branch</th><th>Mode</th><th>Model</th><th>Files</th><th>Duration</th><th>Started At</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Sessions}}
|
||||
<tr>
|
||||
<td><a href="/r/{{$.EncodedRepo}}/{{.SessionID}}">{{.SessionID | printf "%.8s"}}…</a></td>
|
||||
<td>{{.GitBranch}}</td>
|
||||
<td>{{if .ReviewMode}}{{.ReviewMode}}{{else}}-{{end}}</td>
|
||||
<td><code>{{.Model}}</code></td>
|
||||
<td>{{.FileCount}}</td>
|
||||
<td>{{formatDuration .DurationSec}}</td>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue