You've already forked agentic-coding-workflow
bugfix
This commit is contained in:
@@ -108,6 +108,12 @@ type Process struct {
|
||||
StartedAt time.Time
|
||||
KilledByUs atomic.Bool // true → exited,false → crashed
|
||||
done chan struct{} // monitor 退出时 close
|
||||
|
||||
// relayCancel 取消 relay 的会话级 context。该 context 由 Spawn 用
|
||||
// context.Background() 派生,独立于调用方的 spawn ctx(spawn ctx 在 Spawn
|
||||
// 返回后立即取消),故 relay 的 reader/writer/persist/permission Decide 在整个
|
||||
// 会话生命周期内都使用未取消的 ctx。onExit 调用 relayCancel 完成 relay teardown。
|
||||
relayCancel context.CancelFunc
|
||||
}
|
||||
|
||||
// stderrRing 是固定行数 ring buffer,monitor 退出时取 tail 写 last_error。
|
||||
@@ -237,6 +243,12 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
|
||||
s.log,
|
||||
)
|
||||
|
||||
// relay 的会话级 context:独立于调用方的 spawn ctx(生产调用方在 Spawn 返回后
|
||||
// 立即 cancel spawn ctx)。relay 的 reader/writer/persist/permission Decide 必须
|
||||
// 在整个会话生命周期内使用未取消的 ctx,否则 prompt 被丢、事件停止持久化、权限
|
||||
// 审批被强制拒绝。teardown 由 onExit 调 relayCancel + Relay.Close(关 r.done)完成。
|
||||
relayCtx, relayCancel := context.WithCancel(context.Background())
|
||||
|
||||
proc := &Process{
|
||||
SessionID: sess.ID,
|
||||
WorkspaceID: sess.WorkspaceID,
|
||||
@@ -251,6 +263,7 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
|
||||
StderrBuf: newStderrRing(s.cfg.StderrBufferLines),
|
||||
StartedAt: time.Now(),
|
||||
done: make(chan struct{}),
|
||||
relayCancel: relayCancel,
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
@@ -259,7 +272,7 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
|
||||
|
||||
go s.drainStderr(proc)
|
||||
go s.monitorProcess(proc)
|
||||
go relay.Run(ctx, handlers.SessionContext{
|
||||
go relay.Run(relayCtx, handlers.SessionContext{
|
||||
SessionID: sess.ID,
|
||||
WorkspaceID: sess.WorkspaceID,
|
||||
UserID: sess.UserID,
|
||||
@@ -268,6 +281,7 @@ func (s *Supervisor) Spawn(ctx context.Context, sess *Session, kind *AgentKind,
|
||||
ToolAllowlist: kind.ToolAllowlist,
|
||||
})
|
||||
|
||||
// 握手仍走调用方的 spawn ctx,保留 SpawnTimeout 截止语义。
|
||||
if err := s.handshake(ctx, sess, kind, relay, proc, extraEnv); err != nil {
|
||||
s.log.Error("acp.handshake_failed", "session_id", sess.ID, "err", err.Error())
|
||||
s.Kill(ctx, sess.ID, s.cfg.KillGrace)
|
||||
@@ -516,6 +530,14 @@ func (s *Supervisor) onExit(ctx context.Context, proc *Process, status SessionSt
|
||||
}
|
||||
}
|
||||
|
||||
// 取消 relay 的会话级 context:停止 reader/writer,并让仍阻塞在 Decide / 已派生
|
||||
// 的 handleAgentRequest goroutine 收到 ctx.Done 后退出。在 Relay.Close 之前调,
|
||||
// 二者共同完成 teardown(relayCancel 停 ctx 派生的 goroutine,Close 关 r.done +
|
||||
// 广播 session_terminated)。relayCancel 在早期 spawn 失败路径也可能为 nil。
|
||||
if proc.relayCancel != nil {
|
||||
proc.relayCancel()
|
||||
}
|
||||
|
||||
// 最后关 relay:广播 session_terminated 给 WS subscribers。
|
||||
proc.Relay.Close(string(status), &exitCode)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user