- Client sends OLLIE_SESSION_ID in the request JSON payload
- Broker denies requests with no session identity
- Broker denies requests for sessions that don't exist
- Remove dead SO_PEERCRED logic (client is same process, useless)
- Remove allow-unknown bypass from checkTurnLimit
- executeElevated: add 3-way select (frameCh/ctx.Done/detachCh) so manual
detach works for elevated processes. Previously the default branch called
readFrames synchronously with no way to receive the detach signal.
- README: replace execute_code references with shell, update tool description
to match current single-command interface.
Ensures every Server created by the dispatcher factory has registries
wired at construction time, fixing intermittent 'no session registry'
errors from tool_load/skill_load.
Re-adds the detach boolean to the shell tool args. When true, the
process is immediately backgrounded and its PID returned. This was
removed in the simplification commit 2c36c02 but is needed for
long-running commands (builds, servers, etc).
The elevation broker protocol doesn't support stdin piping.
When a promoted tool runs elevated, wrap the command as:
cat <<'OLLIE_EOF' | /path/to/tool
{json}
OLLIE_EOF
This ensures elevated tools receive their JSON args.
- callPromotedTool now pipes raw JSON object to tool stdin instead of
unpacking positional args. Tools parse their own input.
- Default schema changed from positional array to empty object.
- Registry.Discover() skips files without ollie:prompt marker.
- Registry.Summaries() and Loaded() return sorted results (both
tools and skills registries).
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