Commit Graph

654 Commits

Author SHA1 Message Date
Levi Neely 6396167361 agent: delegate sessionID, cwd, env, uname to session.Session
Continue moving session concerns to the session package:
- sessionID → sess.ID()/SetID()
- cwd → sess.CWD()/SetCWD()
- env/envMu → sess.SetEnv()/Env()
- uname → sess.Uname()

Mutex responsibilities are cleanly split:
- session.Session.mu protects: state, reply, cwd, id
- session.Session.envMu protects: env map
- agent.mu protects: history, runtime (agent-specific state)
2026-07-29 18:31:18 +02:00
Levi Neely 64f3f18573 agent: delegate bus, fifo, state, reply to session.Session
Move session-scoped concerns out of the agent struct:
- Bus() → sess.Bus()
- Queue()/PopQueue() → sess.Queue()/PopQueue()
- State()/setState() → sess.State()/SetState()
- Reply() → sess.Reply()/SetReply()

Remove corresponding fields from agent struct. Agent-level
WaitChange still uses its own changeMu/changeCond since it
observes multiple fields (state, usage, ctxsz, cwd, agent).
2026-07-29 18:28:14 +02:00
Levi Neely 457ec2312f session: new package for agent runtime environment
Defines Session (ID, CWD, state, env, bus, FIFO) as the runtime
environment that hosts an agent. This is the foundation for separating
session concerns from agent reasoning concerns.
2026-07-29 18:23:04 +02:00
Levi Neely 498278665f rename agent.Session → agent.History
The Session type in agent/ is purely a conversation accumulator
(message history, token tracking, compaction state). Rename it to
History to free up 'Session' for the runtime environment concept
in the upcoming agent/session split.
2026-07-29 18:21:34 +02:00
Levi Neely 27ee375892 README: fix session lifecycle, remove /tmp/ollie reference 2026-07-29 18:14:41 +02:00
Levi Neely bf137f0265 update README for new package layout 2026-07-29 18:12:01 +02:00
Levi Neely 2ea13cd611 restructure: drop pkg/, split tools/execute into focused packages
- Drop pkg/ prefix (Go anti-pattern): ollie/pkg/X → ollie/X
- Split tools/execute god package:
  - execute/: shell execution, sandboxing, elevation client, remote SSH
  - tools/: interfaces + registry + discovery + schema parsing
  - detach/: background process management (ring buffer, signal)
- Promote internal/sandbox → sandbox/
- Absorb config/ into agent/config.go (agent definition loading)
- Merge remote/ into execute/remote.go (RemoteServer)

All tests pass.
2026-07-29 18:10:25 +02:00
Levi Neely 2372c057bb elevate: require valid session identity for all requests
- 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
2026-07-29 16:30:16 +02:00
Levi Neely c25f59ac7b elevate: per-turn rate limiter (max 3 per turn)
Adds a per-session burst counter that limits elevation requests to 3
per agent turn. Resets on the next user prompt submission.

Rate-limited requests get a distinct error message:
  elevate-broker: rate-limited (max 3 per turn)

This guards against runaway agents flooding the notification daemon
(D-Bus is the least robust transport for this).
2026-07-29 16:22:15 +02:00
Levi Neely c051a72ba4 shell: fix elevated detach + update docs
- 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.
2026-07-29 14:44:11 +02:00
Levi Neely 38db3db4f2 agent: add WatchAgent support and notify on /agent change
- Add WatchAgent constant to WaitChange fields
- Add WatchAgent case in WaitChange read() function
- Call notifyChange() in /agent command after setting agentName

This enables the D-Bus adapter to detect agent changes and emit
ConfigChanged signals so the GUI can refresh the session list.
2026-07-29 11:03:55 +02:00
Levi Neely 6941c372d8 execute: add WithToolRegistry/WithSkillsRegistry Options
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.
2026-07-29 10:50:26 +02:00
Levi Neely fb21228ca1 agent: keep 'calling:' state during tool execution, not 'thinking'
Previously, the Output callback set state to 'thinking' on every tool
event (including streaming chunks), so the state flickered immediately
away from 'calling:'. Now:

- Tool events no longer trigger setState('thinking')
- The loop emits a 'state' event with 'thinking' at the top of each
  iteration (before calling the backend), which is the correct time
  to transition.
- New 'state' event role in Output callback for explicit state transitions.

This keeps the detach button visible in the GUI during tool execution.
2026-07-29 09:33:46 +02:00
Levi Neely a9642a9be1 execute: stop streaming output to agent after process detach
When a process is detached, nil out lw.stream so output no longer
leaks to the agent's chat stream. Only the ring buffer captures
subsequent output.
2026-07-29 09:28:06 +02:00
Levi Neely 0e1c0f199d shell: restore detach field for autonomous background processes
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).
2026-07-29 09:19:03 +02:00
Levi Neely 12e3338b69 tools: handle string 'true' for elevated flag
Kiro's bridge sends elevated as a string rather than a boolean.
Use a type switch to handle both cases.
2026-07-29 09:14:55 +02:00
Levi Neely 3b05b50b47 tools: pipe stdin JSON via heredoc for elevated calls
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.
2026-07-29 08:52:53 +02:00
Levi Neely 75b76b118e tools: pipe JSON args to stdin, sort tool/skill lists
- 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).
2026-07-29 08:47:06 +02:00
ollie d5c591ad26 add elevated flag to shell and callPromotedTool; thread through to executeElevated 2026-07-29 00:41:40 +02:00
ollie 9ea56242c3 callPromotedTool: run tool scripts through sandbox instead of exec directly 2026-07-29 00:35:07 +02:00
ollie e3a9ff4bf3 add skills registry and skill_list/skill_load/skill_active built-in dispatchers 2026-07-29 00:16:54 +02:00
ollie 852ce1e41b update core README to reference embedded system prompt 2026-07-28 23:32:13 +02:00
ollie e9644e7a3d add built-in tool_active: list currently loaded/promoted tools 2026-07-28 23:24:33 +02:00
ollie 6735a6ab26 add built-in tool_list and tool_load tools 2026-07-28 23:21:42 +02:00
ollie ba9f605119 tool registry: cache tier/parallel metadata in ToolInfo, drop hard-coded tables 2026-07-28 23:15:52 +02:00
ollie 2c36c023aa execute_code -> shell: simplify to single bash command, remove steps/parallel/detach/language 2026-07-28 23:03:31 +02:00
ollie 1b05433a5b strip execute_code to bash-only; remove language detection; run promoted tools directly 2026-07-28 22:59:44 +02:00
ollie 6bd77276ee remove call_tool and pipe implementations 2026-07-28 22:51:47 +02:00
ollie 18d00191f8 remove call_tool and pipe references from docs and prompts 2026-07-28 22:47:06 +02:00
ollie b26bd7f580 remove allowExecutors from config, execute server, and agent JSONs 2026-07-28 22:39:17 +02:00
ollie dce77f0b8d merge registry into execute: one server, one routing table, deterministic arg ordering 2026-07-28 22:08:44 +02:00
ollie f08e0abdf0 core: support dynamic tool registration 2026-07-28 14:13:08 +02:00
ollie 3fb5528c97 flushSave persists backend and model 2026-07-27 20:07:17 +02:00
ollie dfc387d7b8 sanitize invalid ToolCall.Arguments before save; atomic write 2026-07-27 20:01:31 +02:00
ollie 08c9b3dc76 fix unused desc variable in ReactTo 2026-07-27 19:55:11 +02:00
ollie 52849794e8 stop emitting reaction events to chat log; badges handle display 2026-07-27 19:54:39 +02:00
ollie 05524b8aa7 add Reactions() method to Core interface 2026-07-27 19:47:16 +02:00
ollie af9a22b1db response IDs and structured reactions with exact targeting 2026-07-27 19:12:12 +02:00
ollie c656846cce categorize emoji reactions as positive/negative/confused with tracked counters 2026-07-27 18:30:01 +02:00
Levi Neely 96a140a83c add React() for emoji reactions on assistant messages
New method on the Core interface that appends a lightweight user
message to session history without triggering a model turn. The
agent sees the reaction as context on its next turn.

Used by the 9P react file: echo emoji > s/{id}/react
2026-07-27 15:19:33 +02:00
Levi Neely 273a31c5f1 emit post-stream suffixes to chat output
When tool results are streamed, suffixes appended after execution
(truncation hints, user-interruptions, PostTool context) were only
written to the stored message history but never emitted to the chat
stream. This meant they never appeared in D-Bus signals or the chat
file.

Accumulate suffixes explicitly and emit them as a final event when
streaming was active, guaranteeing they appear at the end of the
tool output in all output paths.
2026-07-27 13:07:41 +02:00
Levi Neely 75f11a7dc9 enforce 128KB tool result ceiling unconditionally
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.
2026-07-27 13:02:45 +02:00
Levi Neely 8973881c0a elevate: remove SSH agent proxy (unnecessary with integrated broker) 2026-07-27 11:06:21 +02:00
Levi Neely 116c7fa671 elevate: add ParsePolicy helper 2026-07-27 11:03:18 +02:00
Levi Neely bd40dc9637 sandbox: remove superpowerd integration
Elevation is now handled by the integrated broker in olliesrv.
No longer wraps commands with superpowers run-session.
2026-07-27 10:57:07 +02:00
Levi Neely fb8f4acff1 elevate: show key comment instead of fingerprint in notifications 2026-07-27 10:51:54 +02:00
Levi Neely d79861ff7c elevate: SSH agent proxy with approval gating
Proxies SSH agent requests to the real agent, intercepting
Sign/SignWithFlags for approval via the same broker flow
(notification + persist). Key fingerprints can be persisted
to auto-approve future sign requests.
2026-07-27 10:49:26 +02:00
Levi Neely c418148dc8 elevate: integrated elevation broker package
Core elevation broker that replaces the superpowerd adapter.
Handles command execution outside the sandbox with human-in-the-loop
approval via desktop notifications.

- Policy store: YAML-backed global policy + in-memory session policies
- Request lifecycle: 300s TTL, approve/deny/persist resolution
- Command execution: bash -c with caller env/cwd, streaming d/x frames
- SO_PEERCRED for caller identification
- NotifyFunc callback for UI integration (D-Bus, 9P, etc.)
2026-07-27 10:44:18 +02:00
ollie d903980256 persist usage/cost data across session restarts 2026-07-26 19:01:19 +02:00
ollie 95557b35ab persist active sessions under active directory 2026-07-26 12:10:11 +02:00