- Pass caller context into Executor.Execute so cancellation reaches
the subprocess immediately
- Use Setpgid + SIGKILL on process group to kill grandchild processes
- Add context to ToolExecutor signature and thread it through dispatch
- Reset agent state to idle after drainAgent
- Rollback incomplete session turn on interrupt
Five improvements for cost/focus efficiency:
1. Budget now accounts for fixed per-request overhead (system prompt +
tool schemas), which were previously invisible to ContextBuilder and
could silently exceed intended limits by 30-50%.
2. Tail counting now only counts user and plain-assistant (no tool_calls)
messages toward TailMessages quota. Processed tool exchanges between
conversational turns are included but do not crowd out genuine context.
Trailing in-progress exchanges are always preserved and free.
3. BoundedHistory / BoundedHistoryWithNotice deduplicated into a single
buildBounded(injectNotice bool) private helper.
4. O(n²) prepend in the greedy inclusion loop replaced with
append+slices.Reverse.
5. exec.Executor.MaxOutputChars replaces the hardcoded 8000-char const.
Initialised from OLLIE_TOOL_OUTPUT_CHARS env var, defaults to 8000.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts execute_code into a shared ollie/exec package so anvillm-mcp
and ollie's agent loop can both use it. Includes sandboxed execution,
dangerous-pattern validation with per-Executor rate limiting, 9P tool
reading, and pipeline construction.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>