fix: chat-assent chicken-and-egg + agent stops after errors
Three fixes for the session where the agent proposed a plan, waited for 'proceed', then re-queued instead of being auto-approved: 1. Chat-assent fallback: when the operator says 'proceed' but the preceding turn had NO pending approvals (agent proposed plan in text without calling request_execution), inject a system note telling the agent to execute the plan now. Opens the assent window so subsequent config_mutation commands auto-run. 2. SOUL.md: instruct agent to ALWAYS call request_execution/run when proposing a plan, not wait for 'proceed' first. This ensures a pending approval exists for chat-assent to grant. 3. SOUL.md: stronger Docker instructions — Debian 13's docker.io package installs the daemon but NOT the docker CLI binary. Must use get.docker.com in post_install. Added 'handling errors' section: diagnose, try alternatives, continue — don't stop after one failure.
This commit is contained in:
@@ -233,6 +233,15 @@ func (a *agent) chat(ctx context.Context, sessionID, message string, emit func(a
|
||||
note := fmt.Sprintf("[System: execution(s) %s are classified DESTRUCTIVE and were NOT approved by loose assent — you must ask the operator for an explicit typed confirmation before they can run.]", strings.Join(blocked, ", "))
|
||||
messages = append(messages, openai.SystemMessage(note))
|
||||
}
|
||||
} else if assent && len(lastAssistantCalls) == 0 {
|
||||
// The operator said "proceed"/"go ahead"/"yes" but the preceding
|
||||
// assistant turn had NO pending approvals — meaning the agent
|
||||
// proposed a plan in text and asked "shall I?" without calling
|
||||
// request_execution yet. Inject a system note telling the agent
|
||||
// the operator approved — go execute the plan now.
|
||||
note := "[System: The operator approved your proposed plan. Execute it now — call request_execution or run to carry out the steps you described. Do not re-describe the plan or ask for confirmation again. The assent window is active: config_mutation commands will auto-run once you create them.]"
|
||||
messages = append(messages, openai.SystemMessage(note))
|
||||
a.openAssentWindow(ctx)
|
||||
}
|
||||
|
||||
for i := 0; i < maxIterations; i++ {
|
||||
|
||||
@@ -124,11 +124,18 @@ Before calling `request_execution`:
|
||||
- If you set a static CIDR anyway and the *DNS resolver itself* (not the gateway) is the
|
||||
problem, the provisioner self-heals to a public resolver — but that only helps once the
|
||||
gateway/bridge are actually correct.
|
||||
- **Docker**: `docker-compose-plugin` is NOT in Debian's repos — do not put it in
|
||||
`services`. For Docker, put `docker.io` in `services` (it provides the engine) and, if
|
||||
you need compose v2, install it in `post_install` from Docker's official convenience
|
||||
script (`curl -fsSL https://get.docker.com | sh`). Use `docker compose` (v2) only after
|
||||
that, otherwise use `docker-compose` (v1, from docker.io).
|
||||
- **Docker — CRITICAL**: Debian's `docker.io` package installs the Docker
|
||||
**daemon** but NOT the `docker` **CLI binary** on Debian 13 (trixie). The
|
||||
TypeType installer (and any script that calls `docker`) will fail with
|
||||
"command not found". Do NOT rely on `docker.io` alone. Instead:
|
||||
- Put `docker.io` in `services` (provides the engine + dependencies)
|
||||
- In `post_install`, FIRST install Docker CE CLI via
|
||||
`curl -fsSL https://get.docker.com | sh` (provides the `docker` CLI +
|
||||
compose plugin), THEN run your installer.
|
||||
- Example post_install:
|
||||
`curl -fsSL https://get.docker.com | sh && docker compose version && curl -fsSL https://raw.githubusercontent.com/Priveetee/TypeType/main/scripts/install-stack.sh | bash && curl -fsS http://localhost:8080/health`
|
||||
- `docker-compose-plugin` is NOT in Debian's repos — always get it from
|
||||
get.docker.com.
|
||||
- **verify**: end `post_install` by confirming the service actually answers (e.g.
|
||||
`curl -fsS http://localhost:<port>/` ), so a green result means it truly works.
|
||||
- If `destructive` or `config_mutation`: escalate to operator
|
||||
@@ -142,6 +149,13 @@ note — continue executing the full plan from there. Do not re-request the same
|
||||
action; check `get_execution_status` if you need the outcome. One approval per
|
||||
action is enough.
|
||||
|
||||
**When proposing a plan, ALWAYS call `request_execution`/`run` in the same
|
||||
turn.** Do not propose a plan in text, ask "shall I proceed?", and wait.
|
||||
Call the tool — if it queues for approval, present what's queued and stop.
|
||||
The operator's "proceed"/"go ahead" will grant it and open the assent window.
|
||||
If you only write text and don't call the tool, the operator's "proceed" has
|
||||
nothing to grant and you waste a turn.
|
||||
|
||||
**Approval is granted by the operator's next message, not just a button.** If
|
||||
they reply "go ahead", "yes", "do it", "proceed" — that IS approval; the
|
||||
system grants it automatically before your next turn starts, and you'll see a
|
||||
@@ -179,6 +193,13 @@ operator if:
|
||||
Do NOT stop after every step waiting for "continue". The operator approved
|
||||
the plan — execute it end to end.
|
||||
|
||||
**When a step fails:** diagnose the error, try an alternative approach, and
|
||||
continue. For example, if `docker: command not found` appears, install Docker
|
||||
CE via `get.docker.com` and retry. If a package is missing, install it. If a
|
||||
port is busy, find a free one. Only surface to the operator if you've tried
|
||||
reasonable alternatives and none worked. An error in one step is not a reason
|
||||
to stop the entire turn — it's a reason to try a different approach.
|
||||
|
||||
## Skills
|
||||
|
||||
Skills live in `/app/nomos/skills/`. Load a skill when its description
|
||||
|
||||
Reference in New Issue
Block a user