启动项目逻辑

This commit is contained in:
2026-06-09 22:43:29 +08:00
parent d5a28b11a3
commit f4a7c770af
43 changed files with 3797 additions and 42 deletions
+19 -3
View File
@@ -27,6 +27,7 @@ import (
"github.com/yan1h/agent-coding-workflow/internal/audit"
"github.com/yan1h/agent-coding-workflow/internal/infra/crypto"
"github.com/yan1h/agent-coding-workflow/internal/infra/notify"
procgrp "github.com/yan1h/agent-coding-workflow/internal/infra/proc"
"github.com/yan1h/agent-coding-workflow/internal/mcp"
"github.com/yan1h/agent-coding-workflow/internal/workspace"
)
@@ -95,6 +96,7 @@ type Process struct {
WorktreeID *uuid.UUID // 子 worktree 时填,用于 release
Cmd *exec.Cmd
group procgrp.Group // 进程树句柄(整树终止),Spawn 时 Prepare+Adopt
Stdin io.WriteCloser
Stdout io.ReadCloser
Stderr io.ReadCloser
@@ -173,6 +175,11 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
cmd.Dir = sess.CwdPath
cmd.Env = osEnv
// 进程树管理:Prepare 须在 Start 前(Unix Setpgid),Adopt 须在 Start 后
// (Windows Job Object)。终止时整树清理,避免 agent 派生的子孙进程残留。
group := procgrp.NewGroup()
group.Prepare(cmd)
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, fmt.Errorf("stdin pipe: %w", err)
@@ -189,6 +196,10 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
if err := cmd.Start(); err != nil {
return nil, fmt.Errorf("start: %w", err)
}
if err := group.Adopt(cmd); err != nil {
_ = cmd.Process.Kill()
return nil, fmt.Errorf("adopt process group: %w", err)
}
var decider handlers.PermissionDecider
if s.permSvc != nil {
@@ -215,6 +226,7 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
UserID: sess.UserID,
IsMain: sess.IsMainWorktree,
Cmd: cmd,
group: group,
Stdin: stdin,
Stdout: stdout,
Stderr: stderr,
@@ -307,9 +319,9 @@ func (s *Supervisor) Kill(ctx context.Context, sid uuid.UUID, grace time.Duratio
proc.KilledByUs.Store(true)
// 平台差异:Unix 走 SIGTERM + grace + 强 Kill;Windows 直接 Kill。
// 实现见 supervisor_unix.go / supervisor_windows.go
s.unixGracefulTerm(proc, grace)
// 整树终止:Unix 走 SIGTERM(-pgid) + grace + SIGKILL(-pgid);Windows 关闭
// Job 句柄触发 KILL_ON_JOB_CLOSE。实现下沉至 internal/infra/proc
proc.group.TerminateGroup(proc.done, grace)
select {
case <-proc.done:
@@ -375,6 +387,10 @@ func (s *Supervisor) monitorProcess(proc *Process) {
delete(s.procs, proc.SessionID)
s.mu.Unlock()
// 释放进程树句柄(Windows 关闭 Job handle;Unix no-op)。done 已 close、
// 进程已 Wait 返回,此处 Close 不影响 onExit-must-not-relock 不变量。
proc.group.Close()
status := SessionExited
if !proc.KilledByUs.Load() {
status = SessionCrashed