This commit is contained in:
2026-06-22 08:55:57 +08:00
parent dbb87823e8
commit 6ade6e8fa9
325 changed files with 41131 additions and 855 deletions
+69
View File
@@ -0,0 +1,69 @@
package brief
import (
"context"
"github.com/yan1h/agent-coding-workflow/internal/infra/git"
)
// RepoOrientation 是仓库的轻量定向信息:当前分支、最近若干提交摘要、脏文件路径。
// 用于给 agent 一个"我现在在哪个分支、最近发生了什么、工作树是否干净"的速览。
type RepoOrientation struct {
Branch string
RecentCommits []string
DirtyFiles []string
}
// IsEmpty 报告该定向信息是否完全为空(无分支、无提交、无脏文件)。
func (o RepoOrientation) IsEmpty() bool {
return o.Branch == "" && len(o.RecentCommits) == 0 && len(o.DirtyFiles) == 0
}
// RepoOrienter 是 brief 对 git 的窄接口:给定目录返回有界的仓库定向信息。
// 让 brief 可在没有真实仓库的情况下被单测(注入 fake orienter)。
type RepoOrienter interface {
Orient(ctx context.Context, dir, branch string, maxCommits, maxDirty int) RepoOrientation
}
// gitClient 是 orienter 对 git.Runner 的最小子集。*git.DefaultRunner 直接满足。
type gitClient interface {
Log(ctx context.Context, dir string, n int) ([]git.Commit, error)
Status(ctx context.Context, dir string) ([]git.FileStatus, error)
}
// gitOrienter 是 RepoOrienter 的生产实现,基于 infra/git 的 Log + Status。
// 设计为"尽力而为且永不致命":任何 git 调用失败只产生部分/空的定向信息,
// 不返回 error,从而不会拖垮整份简报(git 失败不应阻塞 prompt 注入)。
type gitOrienter struct{ g gitClient }
// NewRepoOrienter 用给定 git runner 构造 RepoOrienter。
func NewRepoOrienter(g gitClient) RepoOrienter { return &gitOrienter{g: g} }
func (o *gitOrienter) Orient(ctx context.Context, dir, branch string, maxCommits, maxDirty int) RepoOrientation {
out := RepoOrientation{Branch: branch}
if dir == "" || o.g == nil {
return out
}
if maxCommits > 0 {
if commits, err := o.g.Log(ctx, dir, maxCommits); err == nil {
for _, c := range commits {
short := c.Hash
if len(short) > 8 {
short = short[:8]
}
out.RecentCommits = append(out.RecentCommits, short+" "+c.Subject)
}
}
}
if maxDirty > 0 {
if files, err := o.g.Status(ctx, dir); err == nil {
for i, f := range files {
if i >= maxDirty {
break
}
out.DirtyFiles = append(out.DirtyFiles, f.Path)
}
}
}
return out
}