fix(agent): mark chat-assented executions as continued to prevent race
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

When the chat handler approves a pending execution via chat-assent, the
execution completes in ~2s. The continuation worker detects the completed
execution and calls resumeSession — while the chat handler is still
processing 'go ahead'. Two concurrent LLM calls for the same session cause
empty responses (finish_reason=stop) and race conditions.

Fix: mark the execution as continued immediately after chat-assent grants
it, so the continuation worker skips it. The chat handler will drive the
continuation itself (the model sees 'go ahead' and executes the plan).

VERSION 0.7.2 → 0.7.3
This commit is contained in:
2026-07-15 23:18:16 +02:00
parent d6e180845c
commit ca2ff56a25
2 changed files with 10 additions and 1 deletions

View File

@@ -1 +1 @@
0.7.2
0.7.3

View File

@@ -296,6 +296,15 @@ func (a *agent) chatWith(ctx context.Context, sessionID, message, systemInject s
if ok {
granted = append(granted, p.execID)
slog.Info("nomos: chat-assent granted", "execution", p.execID, "status", status, "session", sessionID)
// Mark as continued so the continuation worker doesn't
// pick up this execution and call resumeSession while the
// chat handler is still processing "go ahead." Without this,
// two LLM calls run concurrently for the same session —
// the chat handler's chat() and the worker's resumeSession()
// — causing empty responses and race conditions.
if execUUID, perr := uuid.Parse(p.execID); perr == nil {
a.store.markContinued(ctx, execUUID)
}
emit(agentEvent{Type: "tool_use", Data: map[string]any{"name": "chat_assent", "args": map[string]any{"execution_id": p.execID}, "id": "assent-" + p.execID}, SessionID: sessionID})
emit(agentEvent{Type: "tool_result", Data: map[string]any{"name": "chat_assent", "result": fmt.Sprintf("Approved via chat assent (%q). Status: %s.", message, status), "id": "assent-" + p.execID}, SessionID: sessionID})