The tool result truncation had two bypasses:
1. Error results were exempt (!isErr condition) — a command returning
output in its error message could flood the context with megabytes
of untruncated data.
2. The streaming callback emitted chunks to the event handler (and
thus D-Bus signals) with no size check, flooding the bus even
when the final stored result would be truncated.
Fix:
- Remove the configurable ToolResultMaxBytes field; use the constant
defaultToolResultMaxBytes (128KB) unconditionally for all results
regardless of success/error status.
- Cap the streaming callback at 128KB so chunks stop being emitted
once the ceiling is reached.
- Cap output embedded in execute server error messages to 8KB as
defense in depth.
BuildRuntime now appends a compact surface listing (name + one-liner)
to the preamble instead of full tool prompts. Full prompts are
available on-demand via ToolPrompt(name) for the /net/dns pattern.
- DiscoverTools: extracts short description from first content line
- BuildRuntime: appends "# Available Tools" with name + description
- ToolPrompt(name): returns full ollie:prompt for a specific tool
- Add Prompt field to tools.ToolInfo
- Add ExtractPrompt parser for ollie:prompt...ollie:end blocks
- Add DiscoverTools to scan tool scripts directory
- BuildRuntime appends discovered tool prompts to preamble
Tool scripts can now embed their usage documentation directly in
the script header. This replaces the separate tools-*.md prompt
files and ensures documentation stays co-located with implementation.
The elevation adapter is now managed by the system service manager
(openrc/systemd), not started on-demand from inside the sandbox.
The on-demand approach was unreliable (needed master token access,
exec chain failures on Gentoo, stale instances on socket).
When the elevated process exits with a non-zero code but produces no
stdout/stderr output, report a cleaner error message instead of the
confusing "Output: " with empty string.
prompt_resolver: guard cmd.Dir with stat check so remote CWDs that
do not exist locally do not cause prompt commands to fail with ENOENT.
server.go: add cancel on all early-return paths to fix go vet
cancel-not-used-on-all-paths warnings.
Previously loadSandboxConfig was called unconditionally, causing
failures on hosts without ~/.config/ollie/sandbox/ even when yolo
mode was enabled. Move the load inside the !Yolo branch.
Add ensureElevateAdapter() which probes the adapter socket and starts
elevate-adapter-start if unreachable. Runs in the execute server
process (outside the sandbox) so the adapter starts unsandboxed.
Rewrite executeElevated to use the same select/detachCh pattern as
executeWithStdin. When both elevated and detach are set, the process
is immediately backgrounded into the detach registry with streaming
output captured in the ring buffer.
Also adds the detach field to the execute_code JSON schema description.
When detach: true is set on a CodeStep, the process is immediately
backgrounded after start. Its stdout/stderr are captured in a 64KB
ring buffer accessible via GetDetachedOutput. The agent can then
inspect and manage the process via process_list/process_output tools.
After detach, cmd.WaitDelay was still 1s, causing Go exec to
kill the process after context cancellation + 1s delay. Clear
both cmd.Cancel and cmd.WaitDelay in the detach path.
When a detached process exits, its output (last 2KB of ring buffer)
is queued as a prompt wrapped in <detached-process-result> tags.
The agent sees it on its next turn (or immediately if idle via Queue).
- InjectSystemEvent(content) added to Core interface
- SetOnExit(fn) added to execute.Server for external hook wiring
Adds Detach, ListDetached, SignalDetached, GetDetachedOutput,
DismissDetached to the Core interface. Implemented on agent struct
via interface type assertions to the execute server.
Also adds ListDetachedRaw() to execute.Server for cross-package
consumption without import cycles.
Allows the user to detach a running process from the agent mid-execution.
The process continues running; output flows to a 64KB ring buffer.
Detached processes can be listed, signaled (TERM/KILL), and dismissed.
- DetachedProcess struct with ring buffer, signal, output methods
- Server.Detach() signals the currently executing process to detach
- Execute() rewritten: cmd.Start() + select on wait/ctx/detach
- cleanupDetached() on Close() sends SIGTERM to all
- OnDetach/OnExit hooks for integration with D-Bus layer
- Remove IsSocial guard from sqliteKiroAuth.ProfileARN(); the Kiro API
now requires profileArn on all requests including personal accounts
- Add OLLIE_KIRO_PROFILE_ARN env var for static token auth
- Add repeated error detection (3x identical error triggers corrective nudge)
- Include expected format in tool dispatch error messages
Moved all 9P FUSE mount code from core to 9p module using lifecycle hooks.
Changes:
- Removed 9P-specific fields (mountProc, mountPath, mountEnabled) from execute.Server
- Removed WithMount(), MountPath(), startMount(), remountIfStale() functions
- Added lifecycle hooks: OnPreDispatch, OnClose, OnEnvSet with corresponding options
- Updated SetEnv(), Close(), and Dispatch() to call hooks instead of hardcoded mount logic
- Fixed tool descriptions to use $OLLIE_TOOLS_PATH instead of 9P-specific $OLLIE/s/$SID/t paths
- Removed unused execute import from agent/commands.go
The core execute server is now harness-agnostic.
- Add ListHandlers map to AgentCoreConfig/agent struct; /skills and /tools
dispatch through it instead of reading local paths directly
- Add ReadPlanStep to AgentCoreConfig; wired by 9p/ directly from sess.plan
- Export NextUncheckedStep([]byte) as pure helper
- Fix prependOlliePath to use OLLIE_CFG_PATH/scripts/x/ instead of $OLLIE/x/
- Add OLLIE_CFG_PATH to EnsureDefaults and managed env var list
Session identity is now a numeric UID (starting at 10000) assigned at
creation and never changed. Session names can be renamed freely without
affecting the 9P identity.
- AgentCoreConfig.Uname carries the principal
- pushSessionEnv sets OLLIE_UNAME on the execute server
- startMount gated by WithMount() option (not env var)
- Close() uses context timeout to avoid hanging on fusermount
The execute server now starts ollie-9p-mount when OLLIE_SESSION_ID is
set, giving each agent session its own FUSE proxy that attaches to
olliesrv with Uname=session_id. Tools see the full namespace through
$OLLIE but all 9P operations carry the session's identity.
Close() tears down the mount on session destroy.
- Wire PlanFile from $OLLIE/s/{id}/plan into agentConfig so plan
re-injection is no longer dead code
- Add missing failureWindow/maxFailures/blockDuration constants
- Replace hand-rolled contains() with strings.Contains
- Fix rm -rf .. regex to match end-of-string and whitespace
- Add TestPlanReinjection covering periodic plan re-surfacing
- Add loop_maxsteps_helpers_test.go with mockResponse/newState/sequentialStream