diff --git a/VERSION b/VERSION index 39e898a..7486fdb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7.1 +0.7.2 diff --git a/cmd/nomos/agent.go b/cmd/nomos/agent.go index 1be0a4b..b83ecee 100644 --- a/cmd/nomos/agent.go +++ b/cmd/nomos/agent.go @@ -315,7 +315,14 @@ func (a *agent) chatWith(ctx context.Context, sessionID, message, systemInject s } if len(granted) > 0 { a.openAssentWindow(ctx, sessionID) - note := fmt.Sprintf("[System: the operator approved pending execution(s) %s via chat assent — they are now running. An assent window is now active for 30 minutes: config_mutation commands will auto-run without re-approval. The approved execution(s) are already dispatched — do not re-request THOSE SPECIFIC ones. But you MUST continue executing the REMAINING plan steps: call update_plan_step(seq=N, status=\"running\") then run(...) for each unstarted step. Do not stop and wait for 'continue'. Only surface to the operator for destructive actions (need typed confirmation) or if you're genuinely stuck after trying alternatives.]", strings.Join(granted, ", ")) + // Brief note: only tells the model WHICH specific executions + // were approved (so it doesn't re-request them). Does NOT say + // "continue the plan" — the model already sees "go ahead" in + // the replayed history and knows to continue. The old verbose + // note ("they are now running... you MUST continue...") made + // the model think work was being done for it, causing empty + // responses (finish_reason=stop, content_len=0). + note := fmt.Sprintf("[System: execution(s) %s were approved by the operator and are now running. Do not re-request those — check get_execution_status if you need the outcome.]", strings.Join(granted, ", ")) messages = append(messages, openai.SystemMessage(note)) } if len(blocked) > 0 { @@ -324,16 +331,16 @@ func (a *agent) chatWith(ctx context.Context, sessionID, message, systemInject s } } else if assent && len(pending) == 0 { // The operator said "proceed"/"go ahead"/"yes" but there are no - // pending approvals from the preceding turn — meaning the agent - // proposed a plan (via propose_plan, possibly with pre-plan research - // tool calls) and asked "shall I?" without calling run yet. Inject - // a system note telling the agent the operator approved — go execute - // the plan now. The old check (len(lastAssistantCalls) == 0) was too - // restrictive: it only fired when the assistant had ZERO tool calls, - // but propose_plan + research tools are tool calls. The right check - // is "no pending APPROVALS" (len(pending) == 0), not "no tool calls." - note := "[System: The operator approved your proposed plan. Execute it now — for each step, call update_plan_step(seq=N, status=\"running\") then run(...) for that step's target, then update_plan_step(seq=N, status=\"done\"). The assent window is active: config_mutation commands will auto-run. Do not re-describe the plan or ask for confirmation again. Do not wait for 'continue' — execute all steps in this turn.]" - messages = append(messages, openai.SystemMessage(note)) + // pending approvals — the agent proposed a plan (via propose_plan) + // and asked "shall I?" Open the assent window silently. Do NOT + // inject a system note: the model already sees "go ahead" in the + // replayed history (the user message was saved to the DB before + // chat() was called, and getRecentMessages replays it). The old + // verbose system note ("The operator approved your proposed plan. + // Execute it now — call update_plan_step then run...") was redundant + // with the user's "go ahead" and caused the model to no-op + // (finish_reason=stop, content_len=0) — the model saw "approved" + + // "running" and concluded there was nothing to do. a.openAssentWindow(ctx, sessionID) }