run: PostRun detached ctx + panic-isolated Cleanup (gadfly #12)
Two convergent gadfly refinements on the PostRun wiring: - PostRun now runs on detach(ctx), not the caller's ctx — a finished/cancelled caller no longer aborts artifact production (3-model: glm-5.2/minimax/deepseek). - Cleanup is panic-isolated via safeCleanup (recover+log), matching runPostRun, so a misbehaving teardown can't clobber an otherwise-successful run (deepseek). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+4
-2
@@ -218,7 +218,7 @@ func (e *Executor) Run(ctx context.Context, ra RunnableAgent, inv tool.Invocatio
|
|||||||
if inv.SessionToolFactory != nil {
|
if inv.SessionToolFactory != nil {
|
||||||
st := inv.SessionToolFactory(&runSession{mailbox: mailbox})
|
st := inv.SessionToolFactory(&runSession{mailbox: mailbox})
|
||||||
if st.Cleanup != nil {
|
if st.Cleanup != nil {
|
||||||
defer st.Cleanup()
|
defer safeCleanup(st.Cleanup) // panic-isolated, like runPostRun
|
||||||
}
|
}
|
||||||
for _, t := range st.Tools {
|
for _, t := range st.Tools {
|
||||||
if err := toolbox.Add(t); err != nil {
|
if err := toolbox.Add(t); err != nil {
|
||||||
@@ -338,7 +338,9 @@ func (e *Executor) Run(ctx context.Context, ra RunnableAgent, inv tool.Invocatio
|
|||||||
if runRes != nil {
|
if runRes != nil {
|
||||||
transcript = runRes.Messages
|
transcript = runRes.Messages
|
||||||
}
|
}
|
||||||
res.PostRunResult = runPostRun(ctx, postRun, transcript, res.Output, runErr)
|
// Detach from the caller's ctx: a finished/cancelled caller must not abort
|
||||||
|
// artifact production (the hook owns its own bounding, per its contract).
|
||||||
|
res.PostRunResult = runPostRun(detach(ctx), postRun, transcript, res.Output, runErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
e.finishAudit(ctx, rec, status, res, started, runErr)
|
e.finishAudit(ctx, rec, status, res, started, runErr)
|
||||||
|
|||||||
@@ -74,3 +74,15 @@ func (s *runSession) AttachImages(text string, images ...llm.ImagePart) {
|
|||||||
}
|
}
|
||||||
s.mailbox.push(llm.UserParts(parts...))
|
s.mailbox.push(llm.UserParts(parts...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// safeCleanup runs a SessionTools.Cleanup with panic isolation, so a misbehaving
|
||||||
|
// teardown (temp-dir removal, handle close) can't clobber an otherwise-successful
|
||||||
|
// run via the executor's top-level recover.
|
||||||
|
func safeCleanup(fn func()) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
slog.Error("run: session Cleanup panicked", "panic", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user